Swift协议初始值设定项阻止向结构添加更多存储属性

Swift协议初始值设定项阻止向结构添加更多存储属性,swift,initialization,swift-protocols,Swift,Initialization,Swift Protocols,TL;博士: 我想要一个协议来提供默认的init行为,但是编译器拒绝采纳者添加更多的存储属性。我用组合而不是继承解决了这个问题,但是我最初的方法有什么问题吗 动机 我想自动化从设计规范到运行时规范的对象转换。我使用了缩放CGSize的示例,但其目的比几何布局更一般。(例如,我的解决方案不是采用/拒绝/重写自动布局。) 代码 您可以将其粘贴到操场上,它将正确运行 protocol Transformable { var size : CGSize { get }

TL;博士

我想要一个协议来提供默认的
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
是不可变的,我希望这样。向我解释为什么我想要的是错的。。。此页面太小,无法包含我尝试过的所有变体,但可能我错过了简单的答案。

您是否希望继承实现?没有,但是。。如果这听起来有点油嘴滑舌,请原谅,但您可以使用类来实现这一点。谢谢你的问题,虽然它给我带来了一些好的阅读,谢谢你的参考。你也可能喜欢芭芭拉·利斯科夫或伯特兰·迈耶。