[swift-evolution] [Review] SE-0026 Abstract classes and methods
Gwendal Roué
gwendal.roue at gmail.com
Fri Mar 4 14:57:53 CST 2016
> Le 4 mars 2016 à 21:28, Wallacy <wallacyf at gmail.com> a écrit :
>
> This should be resolved when PwS <http://article.gmane.org/gmane.comp.lang.swift.evolution/3082>(Protocol with Storage) get alive:
>
> […]
>
> This is another proposal, but the idea is improve the current protocol model instead to create another type just because a single skill.
Yes. But I wanted to talk about visibility, not about storage. Quoting myself:
The problem with protocols is that the implementation detail referenceRow has to be public (when it should remain an implementation detail), and that the conforming types must provide it (when they should not even know about its existence):
// Framework land
public abstract class DatabaseRecord {
// DatabaseRow initializer
public required init(row: DatabaseRow) {
referenceRow = row
}
// The table name
public abstract class func databaseTableName() -> String
// What should be stored in the database
public abstract var persistedRow: DatabaseRow
// True if record has been changed since last fetch
public var hasChanges: Bool {
// return complex computation based on referenceRow and persistedRow
}
// Hidden implementation detail
internal var referenceRow: DatabaseRow
}
// User land
class Person : DatabaseRecord {
var name: String
class func databaseTableName() -> String { return "persons" }
init(row: DatabaseRow) {
name = row["name"]
super.init(row)
}
var persistedRow: DatabaseRow { return Row("name": name) }
}
let person = Person(row: …)
person.name // "foo"
person.hasChanges // false
person.name = "bar"
person.hasChanges // true
How do we express this with protocols?
// Framework land
public protocol DatabaseRecord {
var referenceRow: DatabaseRow { get set }
var persistedRow: DatabaseRow { get }
static func databaseTableName() -> String
init(row: DatabaseRow)
}
extension DatabaseRecord {
public var hasChanges: Bool {
// return complex computation based on referenceRow and persistedRow
}
}
// User land
class Person: DatabaseRecord {
var referenceRow: DatabaseRow
var name: String
init(row: DatabaseRow) {
name = row["name"]
super.init(row)
}
class func databaseTableName() -> String { return « persons" }
var persistedRow: DatabaseRow { return Row("name": name) }
}
let person = Person(row: …)
person.name // "foo"
person.hasChanges // false
person.name = "bar"
person.hasChanges // true
person.referenceRow = … // messed up internal state
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160304/242f85ad/attachment.html>
More information about the swift-evolution
mailing list