[swift-evolution] [Draft] Allow declaration of abstract functions and properties on classes
Pierre Monod-Broca
pierre at monod-broca.fr
Thu Feb 25 06:08:37 CST 2016
+1 to Brent
> Le 25 févr. 2016 à 02:27, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> a écrit :
>
>> 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:
>>
>> • Places an animating UIActivityIndicatorView onscreen
>> • Performs some operation to retrieve some text
>> • Puts the text in a UITextView and places it onscreen
>> • 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:
>>
>> • It forces the developer to write code that should never be executed under normal conditions. This seems like a waste.
>>
>> • 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.
>>
>> • 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.
>
> That's one alternative, yes. Others include:
>
> 1. Having a delegate provide the `retrieveText()` method.
>
> 2. Having a closure property implement the `retrieveText()` method.
>
> 3. Declaring a protocol `ActivityViewControlling` that requires `retrieveText()` and adding the other logic in an `extension ActivityViewControlling where Self: UIViewController`.
>
> I think that 1 or 2 are usually the best way to handle something like this, but let's explore 3 for a minute, because that's a place where Swift could probably be improved.
>
> Currently, Swift allows you to constrain a protocol to only class types:
>
> protocol ActivityViewControlling: class {
> func retrieveText() -> String
> }
> extension ActivityViewControlling where Self: UIViewController {
> ...
> }
> class MyActivityViewController: UIViewController, ActivityViewControlling {
> func retrieveText() -> String { ... }
> }
>
> But when you do that, Swift permits you to use any class type, which is a bit weird semantically—ActivityViewControlling can be applied to any class, but it's really only meant to be applied to subclasses of UIViewController. An ActivityViewControlling type which isn't a view controller is kind of meaningless.
>
> // Why can I do this?
> class PossibleButUseless: ActivityViewControlling {
> func retrieveText() -> String { ... }
> }
>
> Suppose instead we allow a protocol to require that the conforming class inherit from another class. We could then omit the `where` clause and possibly even make the inheritance itself implicit in conforming to the protocol:
>
> protocol ActivityViewControlling: UIViewController {
> func retrieveText() -> String
> }
> extension ActivityViewControlling {
> ...
> }
> class MyActivityViewController: ActivityViewControlling {
> func retrieveText() -> String { ... }
> }
>
> This would also relieve some of the pressure on us to support class-plus-protocol typed variables. In many of these cases, *all* types conforming to the protocol should be subclasses of a particular class, but there's no way to express that in the type system. Subclass-only protocols would correct that shortcoming.
>
> Subclass-only protocols would cover most, if not all, of the use cases of abstract classes, but I think they would be a less dramatic change to Swift, because protocols are already types which can't be instantiated and impose requirements on their subtypes. I therefore believe they would be a better, more Swift-like approach to the problem abstract classes are trying to solve.
>
> --
> Brent Royal-Gordon
> Architechies
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list