Em qua, 24 de fev de 2016 às 19:43, Evan Maloney via swift-evolution < swift-evolution@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:
Allow declaration of abstract functions and properties on Swift classes · GitHub
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
<Allow declaration of abstract functions and properties on Swift classes · GitHub;
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.
<Allow declaration of abstract functions and properties on Swift classes · GitHub
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.
<Allow declaration of abstract functions and properties on Swift classes · GitHub
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.
<Allow declaration of abstract functions and properties on Swift classes · GitHub
Design
<Allow declaration of abstract functions and properties on Swift classes · GitHub
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
<Allow declaration of abstract functions and properties on Swift classes · GitHub
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.
<Allow declaration of abstract functions and properties on Swift classes · GitHub
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.
<Allow declaration of abstract functions and properties on Swift classes · GitHub;
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...
}
<Allow declaration of abstract functions and properties on Swift classes · GitHub;
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.
<Allow declaration of abstract functions and properties on Swift classes · GitHub
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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution