Swift: overriding typealias inside subclass

2020-08-11 06:01发布

问题:

So I was thinking about a custom pattern in my project, but I can't get it to work. The main idea is to change the typealias on every subclass to get access to the subclass specific interface.

protocol InstanceInterface: class {

    typealias Interface

    var interface: Interface { get }
}

// Baseclass
protocol FirstClassInterface: class { /* nothing here for the example */ }

class FirstClass: InstanceInterface, FirstClassInterface {

    typealias Interface = FirstClassInterface

    var interface: Interface { return self }
}

// Subclass
protocol SecondClassInterface: FirstClassInterface { 

    func foo()
}

class SecondClass: FirstClass, SecondClassInterface {

    typealias Interface = SecondClassInterface // <--- This does nothing :(

    func foo() { print("hello world") } // Swift 2.0 here
}

// Lets say I want to call foo trough the interface
let test = SecondClass()

test.interface.foo() // 'Interface' does not have a member named 'foo'

Is there something I'm doing wrong or do I misunderstand some Swift concepts here?! I do need to subclass here to not to implement everything from super class' protocols over and over again. Is my little pattern even possible? I'd appreciate any help. :)

回答1:

Unfortunately there is no good workaround for this problem.

The main idea to override the typealias would work in this case but consider the following:

protocol TakeAndGet {
    typealias T
    func take(value: T)
    func get() -> T
}

class FirstClass: TakeAndGet {
    typealias T = FirstClass

    var property = 0

    func take(value: T) {
        value.property = 4
    }

    func get() -> T {
        return FirstClass()
    }
}

class SecondClass: FirstClass {

    typealias T = SecondClass

    var property2 = "hello"
}

If the typealias of the SecondClass overrides the other one the take method would work since it takes a subclass which can be treated as the superclass. But the get method cannot implicitly convert FirstClass to SecondClass. Therefore it is not possible to override a typealias.

Now if we want to override the get function with get() -> SecondClass it wouldn't work since it has not the same signature as the one in the superclass. In addition we inherit the get method which results in an ambiguous use:

SecondClass().get() // which type gets returned? SecondClass or FirstClass

So you have to try a different approach.



回答2:

Would something like this work for your purposes?

class MyClass<T> {

}

class MySubclass1: MyClass<String> {

}

class MySubclass2: MyClass<Int> {

}