[swift-evolution] [Draft] Allow declaration of abstract functions and properties on classes

Wallacy wallacyf at gmail.com
Thu Feb 25 05:57:52 CST 2016


There's a time I'm thinking of "Properties on Default Protocol
Implementations
<http://thread.gmane.org/gmane.comp.lang.swift.evolution/2996>" But I not
yet reached a consistent design. I am waiting for some other improvements
get ready to propose something that really works in the long run.

However I believe that all problems related to abstract classes can rightly
be dealt with by improving current protocols.

Em qua, 24 de fev de 2016 às 19:43, Evan Maloney via swift-evolution <
swift-evolution at swift.org> escreveu:

> After Thorsten reminded me yesterday that I wanted this feature too, I
> spent some time writing up proposal to allow declaration of abstract
> functions and properties on Swift classes:
>
> https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c
>
> This is the first draft; all comments welcome!
>
> Thanks,
> E.
>
> ---
>
> Allow declaration of abstract functions and properties on classes
>
>    - Proposal: SE-NNNN
>    - Author: Evan Maloney <https://github.com/emaloney>
>    - Status: *Draft*
>    - Review manager: TBD
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#introduction>
> Introduction
>
> Swift protocols are useful for the declaring interfaces that must be
> provided by conforming entities (in other words: structs, classes and enums).
> Adopters of a given protocol are free to provide any implementation they
> wish, so long as it supplies the necessary interfaces.
>
> Separating *interface* from *implementation* is widely considered to be a
> best practice in software design, and the Swift protocol is designed for
> this use-case.
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#the-problem>The
> Problem
>
> Unfortunately, the protocol does not cover all of the cases where a
> developer might want to specify an interface to be implemented by another
> entity.
>
> For example, consider the class, which allows the creation of an
> inheritance hierarchy. Often, a class in a hierarchy exists merely to
> provide a common implementation to subclasses. Such classes aren't ever
> intended to be instantiated directly; only subclasses will be instantiated.
>
> To illustrate the point, imagine a view controller class that:
>
>    1. Places an animating UIActivityIndicatorView onscreen
>    2. Performs some operation to retrieve some text
>    3. Puts the text in a UITextView and places it onscreen
>    4. Hides the UIActivityIndicatorView
>
> Now imagine you had many cases in your application where you could benefit
> from such a view controller, and each case differed only in the operation
> required to retrieve the text (represented by Step 2 above).
>
> Ideally, you would be able to achieve this by declaring the interface for
> a function without needing to specify an implementation, the same way you
> would with a protocol:
>
> func retrieveText() -> String
>
> In other languages, such as C++, this concept exists in the form of an *abstract
> class*. However, Swift does not support this, so developers are forced to
> provide useless implementations such as:
>
> func retrieveText() -> String
> {
>     fatalError("Subclasses must implement retrieveText()")
> }
>
> The idea here is that subclasses should always provide a retrieveText() implementation,
> and therefore the call to fatalError() should never be hit.
>
> This has a few significant downsides:
>
>    1.
>
>    It forces the developer to write code that should never be executed
>    under normal conditions. This seems like a waste.
>    2.
>
>    Because a default implementation is provided--the one that calls
>    fatalError()--the compiler has no way of knowing that the subclasses
>    are supposed to provide an implementation, too.
>    3.
>
>    If a subclass implementor forgets to provide a retrieveText() function,
>    the error will not be caught until runtime, and not until a user navigates
>    to the affected portion of the application. This may not occur until the
>    application has shipped.
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#proposed-solution>Proposed
> Solution
>
> The proposed solution involves adding support for abstract classes to
> Swift.
>
> This would entail:
>
>    -
>
>    Allowing functions and properties to be declared abstract. An abstract
>    function or property declares the interface without specifying the
>    implementation.
>    -
>
>    Allowing abstract classes to be defined by partially unimplemented
>    protocol conformances. If a class declares conformance to a protocol
>    without providing an implementation for each of that protocol's properties
>    and functions, it is an abstract class.
>    -
>
>    Requiring classes to be explicitly declared as abstract if it has one
>    or more unimplemented functions or properties.
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#detailed-design>Detailed
> Design
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#abstract-functions>Abstract
> functions
>
> Functions can be declared abstract using the abstract keyword, which must
> appear before the func keyword in the declaration. Otherwise, the
> notation is identical to how the function would be declared if it were to
> appear in a protocol:
>
> public abstract func retrieveText() -> String
>
> As long as the abstract keyword appears before the func, the order of
> appearance of the abstract keyword relative to any public, private or
> internal access modifiers is not meaningful.
>
> The following declaration is equivalent to the one above:
>
> abstract public func retrieveText() -> String
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#abstract-properties>Abstract
> properties
>
> Abstract property declarations are identical to what would be found in a
> protocol, but are prefixed with the abstractkeyword, which must appear
> first:
>
> abstract var fileName: String { get }
> abstract var favoriteColor: UIColor { get set }
>
> As is typical with protocol declarations, var is always used and not let.
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#abstract-protocol-conformance>Abstract
> protocol conformance
>
> A class can be made abstract by declaring conformance to a protocol that
> it does not implement fully.
>
> For example, say you had a protocol Vehicle:
>
> protocol Vehicle
> {
>     var name: String { get }
>     var color: UIColor { get }
>     var numberOfWheels: Int { get }
>     var isParked: Bool { get set }
>
>     func driveTo(destination: Location) throws
> }
>
> In your code, you're able to factor out everything except the driveTo() function,
> the implementation of which is vehicle-specific. The common code goes into
> a BaseVehicle class:
>
> abstract class BaseVehicle: Vehicle
> {
>     let name: String
>     let color: UIColor
>     let numberOfWheels: Int
>     var isParked: Bool
>
>     init(name: String, color: UIColor, numberOfWheels: Int, isParked: Bool = true)
>     {
>         self.name = name
>         self.color = color
>         self.numberOfWheels = numberOfWheels
>         self.isParked = isParked
>     }
> }
>
> The BaseVehicle class partially conforms to the Vehicle protocol: the name
> , color, numberOfWheels and isParked properties are provided, but the
> driveTo() function remains unimplemented.
>
> As a result, BaseVehicle is an abstract class and must be declared as
> such.
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#the-abstract-class-declaration>
> The abstract class declaration
>
> A class must be declared as abstract if any of the following are true:
>
>    1. If the class declares one or more abstract functions or properties
>    2. If the class declares conformance to a protocol but does not supply
>    implementations for every one of the functions and properties declared in
>    that protocol.
>    3. If the class inherits from an abstract class and does not supply an
>    implementation for every one of the unimplemented functions or properties.
>
> Classes are marked as abstract by placing the abstract keyword before the
> class keyword at the top of the class declaration, eg.:
>
> public abstract class MyAbstractClass
> {
>     // ...code...
> }
>
> As long as the abstract keyword appears before the class, the order of
> appearance of the abstract keyword relative to any public, private or
> internal access modifiers is not meaningful.
>
> The following declaration is equivalent to the one above:
>
> abstract public class MyAbstractClass
> {
>     // ...code...
> }
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#instantiation>
> Instantiation
>
> Because an abstract class is not a complete implementation, the compiler
> will not allow instantiation of abstract classes.
>
> Attempting to instantiate an abstract class will result in a compiler
> error.
>
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#impact-on-existing-code>Impact
> on Existing Code
>
> None, since this does not affect any existing constructs. Implementation
> of this proposal will not result in any code breakage.
> <https://gist.github.com/emaloney/d0b5bf7dd831d4f7415c#citations>Citations
>
> This idea has been discussed in the following swift-evolution
> <https://lists.swift.org/mailman/listinfo/swift-evolution> mailing list
> threads:
>
>    - [Review] SE-0030 Property Behaviors
>    <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160222/010876.html>
>
>
> _______________________________________________
> 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/20160225/0c81cc66/attachment.html>


More information about the swift-evolution mailing list