protocol ManyProperties {
var a: Int { get }
var b: Int { get }
var c: Int { get }
var d: Int { get }
}
struct S: ManyProperties {
let a: Int
let b: Int
let c: Int
let d: Int
init(a: Int, b: Int, c: Int, d: Int) {
self.a = a
self.b = b
self.c = c
self.d = d
}
}
class C: ManyProperties {
let a: Int
let b: Int
let c: Int
let d: Int
// duplicate initializing
init(a: Int, b: Int, c: Int, d: Int) {
self.a = a
self.b = b
self.c = c
self.d = d
}
}
I know superclass can solve the problem with super.init(...). But how to solve the problem without a superclass?
Whether it is actually more concise depends on how many properties and types are involved, but the following strategy can be useful sometimes:
// The real public interface.
public protocol ManyProperties {
var a: Int { get }
var b: Int { get }
var c: Int { get }
var d: Int { get }
init(a: Int, b: Int, c: Int, d: Int)
}
// The internal shared implementation.
internal struct ManyPropertiesStorage {
let a: Int
let b: Int
let c: Int
let d: Int
}
internal protocol InternalManyProperties : ManyProperties {
init(storage: ManyPropertiesStorage)
var storage: ManyPropertiesStorage { get }
}
extension InternalManyProperties {
public var a: Int { return storage.a }
public var b: Int { return storage.b }
public var c: Int { return storage.c }
public var d: Int { return storage.d }
public init(a: Int, b: Int, c: Int, d: Int) {
self.init(storage: ManyPropertiesStorage(a: a + 1, b: b + 1, c: c + 1, d: d + 1))
}
}
// Short and sweet conformances.
public struct A: ManyProperties, InternalManyProperties {
internal let storage: ManyPropertiesStorage
}
public struct B: ManyProperties, InternalManyProperties {
internal let storage: ManyPropertiesStorage
}
public struct C: ManyProperties, InternalManyProperties {
internal let storage: ManyPropertiesStorage
}
public struct D: ManyProperties, InternalManyProperties {
internal let storage: ManyPropertiesStorage
}
A property requirement can be satisfied with stored properties or computed ones. And your protocol doesn’t have an initializer requirement, and so doesn’t impose how you get the values in there to begin with.
This would be legal:
struct MyType: ManyProperties {
var a: Int { return Int.random(0..<10) }
var b: Int { return Int.random(0..<100) }
var c: Int { return Int.random(-10..<10) }
var d: Int { return Int.random(0..<1) }
}