[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