Swift协议初始值设定项阻止向结构添加更多存储属性
TL;博士: 我想要一个协议来提供默认的Swift协议初始值设定项阻止向结构添加更多存储属性,swift,initialization,swift-protocols,Swift,Initialization,Swift Protocols,TL;博士: 我想要一个协议来提供默认的init行为,但是编译器拒绝采纳者添加更多的存储属性。我用组合而不是继承解决了这个问题,但是我最初的方法有什么问题吗 动机 我想自动化从设计规范到运行时规范的对象转换。我使用了缩放CGSize的示例,但其目的比几何布局更一般。(例如,我的解决方案不是采用/拒绝/重写自动布局。) 代码 您可以将其粘贴到操场上,它将正确运行 protocol Transformable { var size : CGSize { get }
init
行为,但是编译器拒绝采纳者添加更多的存储属性。我用组合而不是继承解决了这个问题,但是我最初的方法有什么问题吗
动机
我想自动化从设计规范到运行时规范的对象转换。我使用了缩放CGSize
的示例,但其目的比几何布局更一般。(例如,我的解决方案不是采用/拒绝/重写自动布局。)
代码
您可以将其粘贴到操场上,它将正确运行
protocol Transformable {
var size : CGSize { get } // Will be set automatically;
static var DESIGN_SPEC : CGSize { get } // could be any type.
init(size: CGSize) // Extension will require this.
}
// A simple example of transforming.
func transform(_ s: CGSize) -> CGSize {
CGSize(width: s.width/2, height: s.height/2)
}
// Add some default behavior.
// Am I sinning to want to inherit implementation?
extension Transformable {
init() { self.init(size: transform(Self.DESIGN_SPEC)) }
// User gets instance with design already transformed. No muss, fuss.
}
// Adopt the protocol...
struct T : Transformable {
let size: CGSize
static let DESIGN_SPEC = CGSize(width: 10, height: 10)
}
// ...and use it.
let t = T()
t.size // We get (5,5) as expected.
但每个伊甸园都有蛇。我想要一个具有另一个属性的可转换的
:
struct T2 : Transformable {
// As before.
let size: CGSize
static let DESIGN_SPEC = CGSize(width: 10, height: 10)
let i : Int // This causes all sorts of trouble.
}
什么<代码>类型“T2”不符合协议“可转换”
我们丢失了设置大小
成员的合成初始值设定项
所以。。。我们把它放回去:
struct T3 : Transformable {
// As before.
let size: CGSize
static let DESIGN_SPEC = CGSize(width: 10, height: 10)
let i : Int
init(size: CGSize) {
self.size = size
self.i = 0 // But this is a hard-coded value.
}
}
但现在我们的新成员是静态确定的。因此,我们尝试添加另一个初始值设定项:
struct T4 : Transformable {
// As before.
let size: CGSize
static let DESIGN_SPEC = CGSize(width: 10, height: 10)
let i : Int
init(size: CGSize) { self.size = size ; self.i = 0 }
// Try setting 'i':
init(i: Int) {
self.init() // Get the design spec properly transformed.
self.i = i // 'let' property 'i' may not be initialized directly;
} // use "self.init(...)" or "self = ..." instead
}
将
i
声明为var
将关闭编译器。但是i
是不可变的,我希望这样。向我解释为什么我想要的是错的。。。此页面太小,无法包含我尝试过的所有变体,但可能我错过了简单的答案。您是否希望继承实现?没有,但是。。如果这听起来有点油嘴滑舌,请原谅,但您可以使用类来实现这一点。谢谢你的问题,虽然它给我带来了一些好的阅读,谢谢你的参考。你也可能喜欢芭芭拉·利斯科夫或伯特兰·迈耶。