Consider the following playground:
import Foundation
protocol StringInitable {
init( string:String )
}
class A : StringInitable {
var stored:String
required init ( string:String ) {
stored = string
}
}
class B : A /*, StringInitable */ {
var another_stored:String
required init ( string:String ) {
another_stored = "B-store"
super.init(string: string)
}
}
func maker<T:StringInitable>(string:String) -> T {
return T(string: string)
}
let instanceA = A(string: "test-maker-A")
let instanceB = B(string: "test-maker-B")
let makerA:A = maker("test-maker-A")
let makerB:B = maker("test-maker-B")
let typeInstanceA = _stdlib_getTypeName(instanceA)
let typeMakerA = _stdlib_getTypeName(makerA)
let typeInstanceB = _stdlib_getTypeName(instanceB)
let typeMakerB = _stdlib_getTypeName(makerB)
From the results the compiler seems to have inferred the correct types but has failed to call the correct initializers. How come I have to explicitly implement StringInitable in the B-class (test by removing the comment in the B class definition) to have the generic function "maker" call the correct initializer?
One protocol can inherit from another in a process known as protocol inheritance. Unlike with classes, you can inherit from multiple protocols at the same time before you add your own customizations on top. Now we can make new types conform to that single protocol rather than each of the three individual ones.
Swift doesn't allow us to declare a class with multiple base classes or superclasses, so there is no support for multiple inheritance of classes. A subclass can inherit just from one class. However, a class can conform to one or more protocols.
A protocol can have properties as well as methods that a class, enum or struct conforming to this protocol can implement. A protocol declaration only specifies the required property name and type.
That smells like a compiler bug for one simple reason: makerB
is a variable of B
type, but it is assigned an instance of A
. This should not be possible, and in fact if you try to print, and more generally to access to, the another_stored
property of the makerB
variable, a runtime exception is raised, and I wouldn't expecting nothing else.
That's because if B
is a subclass of A
, an instance of A
cannot be assigned to a variable of B
type (whereas the opposite is possible).
Assigning a variable of A
type to a variable of B
type is possible though, but only under these conditions:
A
to B
is done (the compiler should error otherwise)A
variable is actually an instance of B
(a runtime exception should be raised otherwise)Note that the compiler didn't just fail to call the correct initializer - it called the initializer of another class
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With