rgkobashi
rgkobashi

Reputation: 2698

Difference when declaring swift protocol using inheritance from another protocol or using where Self

I still don't understand what is the difference when declaring a Swift protocol using inheritance:

protocol SubProtocol: SuperProtocol { ... }

or using where Self

protocol SubProtocol where Self: SuperProtocol { ... }

By doing this on these two ways the results are exactly the same, both options compile fine, and it works, SubProtocol will have the same stuff than SuperProtocol has. So what is the difference?

The only difference I can see is the semantic, one is more clear than the other (see example below). But this is my point of view and I would like to know if someone else thinks the same, or perhaps I am miss-understanding the whole thing.

Example:

protocol Progressable {
    var isInProgress: Bool { get }
}

protocol Downloadable: Progressable {
    func download()
}

protocol ProgressReporting where Self: Progressable {
    func reportProgress() -> Bool
}

For me, Downloadable makes sense it inherits from Progressable, every download is progressable, so that is fine.

But ProgressReporting not necessary needs to inherit from Progressable, for me it would make more sense to constraint it by using where, this way the reader can know that whoever implements it, will need to conform to Progressable too (see the comments on the code below), here is when I think the semantic is different.

class MyClassA: Downloadable {
    var isInProgress: Bool { return true }
    func download() {}

    func foo() {
        /*
         I have access to `self.isInProgress` because this class conforms `Downloadable`
         which inherits from `Progressable`, so this makes sense
         */
        _ = self.isInProgress
    }
}

class MyClassB: ProgressReporting {
    var isInProgress: Bool { return true }
    func reportProgress() {}

    func foo() {
        /*
         I have access to `self.isInProgress` but according to `ProgressReporting` definition,
         this class should be `Progressable` which is not, at least not explicitely
         */
        _ = self.isInProgress
    }
}

I would apreciate if someone can explain me what are the differences 🙂

Thanks in advance.

Upvotes: 4

Views: 150

Answers (1)

Andreas Oetjen
Andreas Oetjen

Reputation: 10209

Speaking about Swift5, there is no difference between the two forms, see Swift 5 Release notes:

Protocols can now constrain their conforming types to those that subclass a given class. Two equivalent forms are supported:

protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ } 

Swift 4.2 accepted the second form, but it wasn’t fully implemented and could sometimes crash at compile time or runtime. (SR-5581) (38077232)

Upvotes: 2

Related Questions