Inheritance Swift协议继承&;泛型函数

Inheritance Swift协议继承&;泛型函数,inheritance,swift,protocols,swift-playground,Inheritance,Swift,Protocols,Swift 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 an

考虑以下游乐场:

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)
<代码>导入基础 协议StringInitable{ 初始化(字符串:字符串) } A类:StringInitable{ 存储的变量:字符串 必需的初始化(字符串:字符串){ 存储=字符串 } } B类:A/*,StringInitable*/{ 存储的变量:String 必需的初始化(字符串:字符串){ 另一个_stored=“B-store” super.init(string:string) } } 函数生成器(字符串:字符串)->T{ 返回T(字符串:字符串) } 让instanceA=A(字符串:“test-maker-A”) 让instanceB=B(字符串:“test-maker-B”) 设makerA:A=maker(“test-maker-A”) 设makerB:B=maker(“test-maker-B”) 让typeInstanceA=\u stdlib\u getTypeName(instanceA) 让typeMakerA=\u stdlib\u getTypeName(makerA) 让typeInstanceB=\u stdlib\u getTypeName(instanceB) 让typeMakerB=\u stdlib\u getTypeName(makerB)
从结果中,编译器似乎推断出了正确的类型,但未能调用正确的初始值设定项。为什么我必须在B类中显式实现StringInitable(通过删除B类定义中的注释进行测试),才能让泛型函数“maker”调用正确的初始值设定项?

这听起来像编译器错误,原因很简单:
makerB
B
类型的变量,但是它被分配了一个
A
的实例。这应该是不可能的,事实上,如果您尝试打印
makerB
变量的
另一个存储的
属性,并且更一般地访问该属性,则会引发运行时异常,我不希望发生其他情况

这是因为如果
B
a
的子类,
a
的实例不能分配给
B
类型的变量(反之亦然)

虽然可以将
a
类型的变量分配给
B
类型的变量,但仅在以下条件下:

  • A
    B
    的显式向下转换已完成(否则编译器将出错)
  • A
    变量引用的实例实际上是
    B
    的实例(否则应引发运行时异常)

请注意,编译器并不是没有调用正确的初始值设定项,而是调用了另一个类的初始值设定项

一旦我在init函数前面添加了“required”说明符,它就为我工作了。