2014-10-06 101 views
8

考虑下面的游乐场:斯威夫特协议继承和泛型函数

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) 

从编译器似乎已经推断出正确的类型,但未能调用正确的初始化结果。为什么我必须在B类中显式实现StringInitable(通过删除B类定义中的注释来测试)才能让泛型函数“maker”调用正确的初始化方法?

+0

它为我的初始化一旦我在初始化函数前面加了“需要”符。 – user965972 2015-06-06 19:45:01

回答

2

由于一个简单的原因,这听起来像是一个编译器错误:makerBB类型的变量,但它被分配了一个A的实例。这不应该是可能的,而事实上,如果你尝试打印,并更广泛地访问时,makerB变量的another_stored性能,运行时异常升高,而我也不会别的不指望。

这是因为如果是BA一个亚类中,A的实例不能被分配给B类型的变量(而相对的是可能的)。

分配A类型的变量,以B类型的变量是可能的,虽然,但仅在这些条件下:

  • AB明确低垂完成(编译器应该否则误差)
  • A变量引用的实例实际上是B的实例(否则应该提出运行时异常)

注意,编译器不只是无法调用正确的初始化 - 它被称为另一个类