Abstract class in Swift?

Is there any progress of swift-evolution of abstract class topic?

Here is My Workaround for it:

class C {
    var x: Int

    init(_ x: Int) {
        self.x = x
    }

    func concreteMethod() {}
}

protocol AbstractMethodRequirementsForC {
    func abstractMethod()
}

typealias AbstractC = C & AbstractMethodRequirementsForC

class ConcrectC: AbstractC { ... }

Thanks.

The question is what do abstract classes buy you in Swift that you don’t already have from protocols. Protocols can supply function implementation, and can require that only classes implement them.

So how important is declaring storage for properties?

The only thing that I have wanted sometimes is the ability to call super on a protocol override of a default implementation. Abstract classes do have that.

5 Likes

I’m also hoping for that. In C++, we can use SuperclassName::methodName to call the default implementation. But in Swift, protocol is not like superclass whose methods can be overridden. In fact, the following code is not allowed.

protocol P {
    func f()
}
extension P {
    func f() {}
}

class C: P {}

class D: C {
    // this `override` will cause a compilation error
    override func f() {}
}

But if you provide the implementation of f in C, it will be fine to override.

2 Likes

Imagine such case where you have lots of properties to initialize in many classes/structs. if we have abstract class, the code may look like this:

abstract class C {
    let x: Int
    let y: Int
    let z: Int

    init(x: Int, y: Int, z: Int) {
        self.x = x
        self.y = y
        self.z = z
    }

   abstract func abstractMethod()
}

class D: C {
    let d: Int
    init(x: Int, y: Int, z: Int, d: Int) {
        self.d = d
        super.init(x: x, y: y, z: z)
    }

    override func abstractMethod() {}
}

class E: C {
    let e: Int
    init(x: Int, y: Int, z: Int, e: Int) {
        self.e = e
        super.init(x: x, y: y, z: z)
    }

    override func abstractMethod() {}
}

If I use protocol, is there any way to avoid the duplicate code of self.xxx = xxx?

Would synthesis of stored properties on conforming types be sufficient? i.e.:

protocol A {
    var x: Int { get set }
    var y: Int { get set }
    var z: Int { get set }
}

struct B: A { 
  /// var x, y, z: Int is auto-synthesized
}
2 Likes

@Josh_Osborne Let me give you an example. How would I implement a decorator pattern the way it is done in GoF book? An abstract class allows you to have a shared storage, a default method implementation and, at the same time, it disallows to instantiate itself, so sub-classes would be able to provide their own implementation, call super and initialize the shared storage.

The only thing that a protocol-based solution doesn’t offer is the storage. That’s something I always wanted, but without having to limit myself to classes. I don’t have a solution, unfortunately.

Link to the original Proposal and Deferred rational

Thus far all the stated shortfalls of protocols vs abstract remain true. There's some movement to add support for a few of them, but whether those will be fully developed and accepted remains to be seen. I still come across instances where an abstract class would feel better than a spider web of protocols, especially in terms of access semantics.

It's been 3+ years now and Swift's use of protocols has been well established. If the core team now (or soon) has the bandwidth to consider it, (also, is there an implementation anywhere?), I would be in favor of the proposal being re-introduced to review.

At first, I was very excited about the possibility of having abstract classes to aid in creating more robust APIs, but, as the deferral note suggests, investing in protocols might be a better idea and I can’t help but agree with that.
I’d be more in favor of focusing on implementing generalized existentials to support such things as existentials of PATs, stored properties in protocols, calling the equivalent of super , and so on.

In case of stored properties in extensions, I’ve had an idea a while ago, but never got around to voicing it. Long story short, it involves allowing stored properties in extensions on non- @frozen struct s and classes from the same module (so that the final layout and size of the extended type will be known and extension-stored-properties are statically “inserted” into extended types by the time the module is compiled) as well as @objc classes from any module (using objc_getAssociatedObject and objc_setAssociatedObject .

I generally agree. Protocols have solved the vast majority of my use cases. I'm also concerned that adding too many things to protocols will increase the complexity too much.

I wonder if there's some sort of in-between solution that could be introduced. Maybe something like "abstract type" or "type protocol" with most/all the features of an abstract type, but that structs/enums/etc would also be able to adopt. Rather than trying to shoehorn in storage/access/super into protocol, they can be added to that new type.

Protocols don’t have to change in order for this to happen, though. If we get stored properties in extensions, then an abstract base class simply becomes a class-bound protocol, which has stored properties in its extensions. Although, stored properties in protocol extensions would be a lot trickier to pull off. Generally, my point is: in my opinion, a huge chunk of what people have wanted be able to get done in Swift could be enabled by having stored properties added to types through extensions.

This is a big issue. You're not simply adding storage in an extension, you're adding storage to a protocol, which currently has none. My understanding is it's not a matter of extending an existing capability, but adding a whole litany of things under the hood which protocols don't currently have.

We'll also need the ability to easily call the extension's implementation, and add access modifiers to protocols in order to satisfy the things desired from an abstract class.

My point is, that's 3 things just to get the basics of an abstract class, and there are also several other often requested features of protocols.

The more things that are wanted to be added to protocols, the more I tend to think the "right" solution is a separate type, rather than bloating protocols.

2 Likes
Terms of Service

Privacy Policy

Cookie Policy