Swift中为何允许将子类实例赋值给父类约束的泛型类型?
protocol Shape {} class Rect: Shape {} class Square: Rect {} struct Box<T: Shape> { let shape: T } let box1 = Box(shape: Square()) let box2: Box<Rect> = box1 // Error: Cannot assign value of type 'Box<Square>' to type 'Box<Rect>' let box3: Box<Rect> = Box(shape: Square()) // 这段代码可以正常编译
问题原因解析
核心差异在于类型推断的时机和上下文约束的作用:
关于
box1赋值给box2报错:
初始化box1时,Swift会根据传入的Square()自动推断泛型参数T为Square,因此box1的类型被固定为Box<Square>。由于Swift泛型默认是不变的,Box<Square>和Box<Rect>是完全独立的类型,不存在继承或转换关系,自然无法直接赋值。关于
box3编译通过:
当直接把Box(shape: Square())赋值给明确标注为Box<Rect>的变量时,Swift会以目标类型为依据,将泛型参数T推断为Rect。此时传入的Square()作为Rect的子类实例,可以隐式向上转换为Rect类型,完全符合Box<Rect>的初始化要求,因此编译合法。
总结来说:前者是先确定了Box<Square>类型后再尝试跨泛型类型赋值(不被允许);后者是直接根据目标类型创建Box<Rect>,利用子类转父类的兼容性完成初始化。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

