[swift-evolution] Proposal: Allow class cluster pattern via dynamic initializer return type
ilya
ilya.nikokoshev at gmail.com
Mon Dec 7 17:39:06 CST 2015
Some thoughts:
1 "self =" is better in inits because of a common pattern of configuring an
object in the second init stage
2 since there is already an existing syntax for protocol implementation
functions, the role of init keyword is basically to stand for "empty
function name" syntax. This sounds interesting.
3 you can also add init to the protocol (with Self return value and
required keyword) for some interesting effects.
4 final init, not class init (because init is already called on the class):
class BaseClass {
init(x: ...) -> Self // regular, inheritable init, Self can be omitted
final init(y:...) -> Self // Self always = BaseClass, can return Derived()
5 yes, that would nicely work with ObjC, even if that was not the original
goal :)
On Tue, Dec 8, 2015 at 02:24 Brent Royal-Gordon via swift-evolution <
swift-evolution at swift.org> wrote:
> > Throughout its frameworks, Apple makes use of the “class cluster”
> pattern as a means to separate the public API out from the (potentially
> complex) internal representations of the data. Clients of the API simply
> use the public API, while under the hood a different implementation is
> chosen to most efficiently represent the provided initialization parameter
> values.
> >
> > Unfortunately, because initializers in Swift are not methods like in
> Objective-C, there is no way to specify what the actual return value should
> be (short of returning nil for failable initializers). This makes it
> *impossible* to actually implement the class cluster pattern in Swift.
>
> I’d actually like to put Objective-C interop aside for a moment. There are
> many class clusters in Objective-C, but most of them are things you rarely
> need to subclass yourself. When was the last time you wrote an NSArray
> subclass? What’s more interesting to me is how we can provide a similar
> native Swift pattern.
>
> Here’s my thinking.
>
> First of all, we call them “class” clusters, but there’s no reason this
> should be only for classes. A “class cluster” is basically a single API
> which offers access to many different implementations of an interface. The
> phrase “many different implementations of an interface” is a hint that we
> should be thinking about protocols.
>
> Here’s what I think Swift should support:
>
> protocol HTTPParameterListType {
> var all: DictionaryLiteral<String, Strong> { get }
> subscript (name: String) -> [String] { get }
> }
>
> // Various implementations include:
> struct JSONParameterList: HTTPParameterList {...}
> struct MultipartParameterList: HTTParameterList {…}
> struct URLEncodedFormParameterList: HTTPParameterList {…}
> struct QueryParameterList: HTTPParameterList {…}
>
> extension HTTPParameterListType {
> protocol init(request: NSHTTPRequest, bodyData: NSData)
> throws {
> switch
> request.valueForHTTPHeaderField(“Content-Type”).map({ MIMEType(rawValue:
> $0) }) {
> case .JSON?:
> return try JSONParameterList(data:
> bodyData)
>
> case .MultipartFormData?:
> return try MultipartParameterList(data:
> bodyData)
>
> case .URLEncodedForm?:
> return try
> URLEncodedFormParameterList(data: bodyData)
>
> default:
> return try QueryParameterList(request:
> request)
> }
> }
> }
>
> // Usage:
> self.parameters = HTTPParameterListType(request: request,
> bodyData: data)
>
> A `protocol init` in a protocol extension creates an initializer which is
> *not* applied to types conforming to the protocol. Instead, it is actually
> an initializer on the protocol itself. `self` is the protocol metatype, not
> an instance of anything. The provided implementation should `return` an
> instance conforming to (and implicitly casted to) the protocol. Just like
> any other initializer, a `protocol init` can be failable or throwing.
>
> Unlike other initializers, Swift usually won’t be able to tell at compile
> time which concrete type will be returned by a protocol init(), reducing
> opportunities to statically bind methods and perform other optimization
> tricks. Frankly, though, that’s just the cost of doing business. If you
> want to select a type dynamically, you’re going to lose the ability to
> aggressively optimize calls to the resulting instance.
>
> Perhaps this feature can then be extended back to classes, with a `class
> init` being an un-inherited initializer which uses `return` to give the
> caller a new object. `self` would be the class object, and only class
> variables and methods would be callable from it. But like I said, I’m not
> particularly interested in Objective-C interop right now.
>
> --
> Brent Royal-Gordon
> Architechies
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151207/e9905b08/attachment.html>
More information about the swift-evolution
mailing list