# Abstract class in Swift?

**URL:** <https://forums.swift.org/t/abstract-class-in-swift/26168>\
**Category:** Discussion\
**Created:** [June 22, 2019, 6:05am UTC](https://forums.swift.org/t/abstract-class-in-swift/26168 "2019-06-22T06:05:28Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 18, 2019, 9:00pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/41 "2019-12-18T21:00:33Z")

</div>

Not really a fan of `required`, but that would be a possibility.

I just think that if you allow `open` classes, then you are admitting that these classes will have some functionality provided by subclasses. From there it immediately follows that abstract classes are needed. If you can say `open`, you must also be able to say `abstract`. Anything else is an omission from the language, which one can obviously live with, but why?

---

<div class="post-metadata">

**Author:** ![dwaite](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dwaite/32/1200_2.png) [@dwaite](https://forums.swift.org/u/dwaite)\
**Post date:** [December 18, 2019, 10:49pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/42 "2019-12-18T22:49:02Z")

</div>

> [@phlegmaticprogrammer](#):
>
> I just think that if you allow `open` classes, then you are admitting that these classes will have some functionality provided by subclasses.

Yes, but I would argue that if a third party framework requires subclassing an open class and it _isn't_ a legacy interface from Objective-C, then its a "code smell" in that framework.

Even with Objective-C, we have delegates and data sources to attempt to reduce the amount of subclassing you need to do to change behavior.

The only instance of an open class in the stdlib is the Encoders/Decoders, which IMHO is a mistake as the internals needed to change encoding/decoding behavior are not externally accessible. I also feel that in this case it is a sign of a bad API - the reason that Encoders have to be classes is because the design of the container interface behind Encodable mandates containers have reference semantics.

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 18, 2019, 11:49pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/43 "2019-12-18T23:49:10Z")

</div>

I am currently implementing a Parsing DSL where using open classes works very well, and I rather like the smell of it. It is not published yet, but I can already give an example:

```
class Calculator : Grammar<CODEPOINT> {
    
    @Nonterminal var Expr : Out<INT>
    @Nonterminal var Sum : Out<INT>
    @Nonterminal var Product : Out<INT>
    @Nonterminal var Num : Out<INT>
    @Terminal var Digit : Out<INT>
    
    var ambiguous : Bool
    
    init?(ambiguous : Bool) {
        self.ambiguous = ambiguous
        super.init()
    }
    
    override func build() {
        add {
            start($Expr)
            
            $Expr.rule {
                $Sum
                
                $Sum.out --> $Expr
            }

            $Sum.rule {
                $Sum[1]
                %!(char == "+")
                $Product
                
                $Sum[1].out + $Product.out --> $Sum
            }

            $Sum.rule {
                $Product
                
                $Product.out --> $Sum
            }

            $Product.rule {
                $Product[1]
                %!(char == "*")
                $Num
                
                $Product[1].out * $Num.out --> $Product
            }
            
            $Product.rule {
                $Num
                
                $Num.out --> $Product
            }
            
            $Num.rule {
                $Digit
                
                $Digit.out --> $Num
            }
            
            
            if !ambiguous {
                $Num.rule {
                    $Num[1]
                    $Digit
                    
                    $Num[1].out * 10 + $Digit.out --> $Num
                }
            }
            
            if ambiguous {
                $Num.rule {
                    $Num[1]
                    $Num[2]
                    
                    $Num[1].out * 10 + $Num[2].out --> $Num
                }
            }
            
            $Digit.rule {
                %!(char.codepoint >= 48 && char.codepoint <= 57)
                char(0).codepoint - 48 --> $Digit
            }
        }
    }
    
}

```

You create a grammar in my DSL by subclassing from Grammar which is an open class. This is very natural, and I don't see anything smelly about that. It would not be possible to use a protocol instead, as Grammar keeps track of internal state that the user of the library should not be exposed to.

---

<div class="post-metadata">

**Author:** ![David\_Sweeris](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/david_sweeris/32/31302_2.png) [@David\_Sweeris](https://forums.swift.org/u/David_Sweeris)\
**Post date:** [December 19, 2019, 1:05am UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/44 "2019-12-19T01:05:35Z")

</div>

> [@phlegmaticprogrammer](#):
>
> I am currently implementing a Parsing DSL where using open classes works very well, and I rather like the smell of it. It is not published yet, but I can already give an example:  
> \<snip\>

Oh, that looks neat! Do you know if/when it'll be made public?

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 19, 2019, 5:13am UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/45 "2019-12-19T05:13:46Z")

</div>

Glad you like the look of it :-) It'll be public before the end of the year.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [December 19, 2019, 6:08am UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/46 "2019-12-19T06:08:12Z")

</div>

Or...make it a struct and pass in the builder 🙂

```swift
let calculator = Grammar<MyCodePoint>(ambiguous: true, builder: { (grammar: Grammar< MyCodePoint) in 
        grammar.add {
            grammar.start(grammer.$Expr)
      
            grammar.$Expr.rule { 
            // etc
})

```

Not saying you should, (obviously I haven't seem the whole structure so I can hardly make that judgement anyway), just that there are usually options.

Anyway, other than the weird casing 😉 it looks cool!

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 19, 2019, 10:53am UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/47 "2019-12-19T10:53:15Z")

</div>

That looks like I have to repeat `grammar.` a thousand times there, just in order to adhere to a dogma ... ;-) Doesn't look like an improvement. But playing the devil's advocate here, could I get rid of the grammar repetition in your example somehow, via something like `import grammar._` ?

---

<div class="post-metadata">

**Author:** ![Ilias\_Karim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ilias_karim/32/2339_2.png) [@Ilias\_Karim](https://forums.swift.org/u/Ilias_Karim)\
**Post date:** [December 19, 2019, 3:40pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/48 "2019-12-19T15:40:39Z")

</div>

It's as @GetSwifty says, abstract classes are considered an anti-pattern. fatalError already allows developers to declare them anyways.

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 19, 2019, 3:55pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/49 "2019-12-19T15:55:06Z")

</div>

I'd say fatalError is an anti-pattern here. Abstract classes are not an anti-pattern if properly used, just like `continue` and `break` are not an anti-pattern if properly used. If you don't know when to use a tool, that's a different issue entirely.

---

<div class="post-metadata">

**Author:** ![Ilias\_Karim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ilias_karim/32/2339_2.png) [@Ilias\_Karim](https://forums.swift.org/u/Ilias_Karim)\
**Post date:** [December 19, 2019, 3:56pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/50 "2019-12-19T15:56:13Z")

</div>

> [@phlegmaticprogrammer](#):
>
> If you don't know when to use a tool, that's a different issue entirely.

At least we can agree on one thing 😆

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [December 19, 2019, 4:02pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/51 "2019-12-19T16:02:27Z")

</div>

> [@phlegmaticprogrammer](#):
>
> But playing the devil's advocate here, could I get rid of the grammar repetition in your example somehow, via something like `import grammar._` ?

I think the most you can do is use a short name (or just $0). If we could do something like kotlin's [`apply`](https://www.geeksforgeeks.org/kotlin-apply-vs-with/) it would allow using it, but I'm doubtful we'll see something like that in Swift anytime soon.

> [@Ilias\_Karim](#):
>
> It's as @GetSwifty says, abstract classes are considered an anti-pattern. fatalError already allows developers to declare them anyways.

I don't think I went _that_ far...regardless there are a lot of (IMO) valid use cases for that type of structure in an OOP ecosystem. Swift having structures that enable other solutions doesn't invalidate all use cases 🙂

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 19, 2019, 4:02pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/52 "2019-12-19T16:02:34Z")

</div>

Here is an example of a class I use in my library:

```
func abstractMethod() -> Never {
    fatalError("need to implement this in subclass")
}

open class Domain {
    
    fileprivate let _rep : Rep
    
    public required init(rep : Any) {
        if let r = rep as? Rep {
            self._rep = r
        } else {
            fatalError("invalid Domain rep: \(rep)")
        }
    }
    
    public required init() {
        self._rep = .None
    }
    
    public required init(domainValue : Any) {
        abstractMethod()
    }
    
    func rep() -> Rep {
        precondition(!_rep.isNone)
        return _rep
    }
    
    func domainRep() -> DomainRep {
        abstractMethod()
    }

    public final func from(domainValue : Any) -> Self {
        return Self(domainValue: domainValue)
    }
    
    public func encode(domainValue : Any) -> DomainValueEncoding {
        abstractMethod()
    }

    public func decode(domainValueEncoding : DomainValueEncoding) -> Any {
        abstractMethod()
    }

}

```

You are telling me this dynamically checked perversion is better than just writing:

```
open class Domain {
    
    fileprivate let _rep : Rep
    
    public required init(rep : Any) {
        if let r = rep as? Rep {
            self._rep = r
        } else {
            fatalError("invalid Domain rep: \(rep)")
        }
    }
    
    public required init() {
        self._rep = .None
    }
    
    public abstract init(domainValue : Any) 
    
    func rep() -> Rep {
        precondition(!_rep.isNone)
        return _rep
    }
    
    abstract func domainRep() -> DomainRep 

    public final func from(domainValue : Any) -> Self {
        return Self(domainValue: domainValue)
    }
    
    public abstract func encode(domainValue : Any) -> DomainValueEncoding 

    public abstract func decode(domainValueEncoding : DomainValueEncoding) -> Any 

}

```

If you do, we have very different opinions about software design :-)

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 19, 2019, 4:23pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/53 "2019-12-19T16:23:04Z")

</div>

Actually, I think the above suggests an easy implementation of abstract classes: Just introduce an `abstract` qualifier as shown above, and say that the semantics is the same as if the body would have been implemented via fatalError. That is an easy rewriting step. Then go ahead and support `abstract` in the type system via warnings / errors at compile time.

---

<div class="post-metadata">

**Author:** ![Ilias\_Karim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ilias_karim/32/2339_2.png) [@Ilias\_Karim](https://forums.swift.org/u/Ilias_Karim)\
**Post date:** [December 19, 2019, 4:24pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/54 "2019-12-19T16:24:09Z")

</div>

No, you misunderstand me. If you find an abstract class in your codebase there may be other problems to solve that use more functional rather than object-oriented solutions. It's rarely a case of interface design, the trees, and rather symptomatic of your holistic architecture, the forest.

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 19, 2019, 4:24pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/55 "2019-12-19T16:24:54Z")

</div>

Yeah, that's just religion.

---

<div class="post-metadata">

**Author:** ![phlegmaticprogrammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/phlegmaticprogrammer/32/11253_2.png) [@phlegmaticprogrammer](https://forums.swift.org/u/phlegmaticprogrammer)\
**Post date:** [December 19, 2019, 4:35pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/56 "2019-12-19T16:35:16Z")

</div>

So just to iterate on that, there would be no such thing as an abstract class, but just abstract initialisers / methods. That should help with dealing with corner cases I've seen people talk about in the evolution mailing list. It is very similar to what @GetSwifty mentioned earlier.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [December 19, 2019, 4:48pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/57 "2019-12-19T16:48:17Z")

</div>

> [@Ilias\_Karim](#):
>
> there may be other problems to solve that use more functional rather than object-oriented solutions.

I would also tend towards finding a more functional/POP solution but Swift, as a language, isn't dogmatic about specific design patterns. OOP has a long history and a massive user/knowledge base. Swift supports users who prefer that approach as well as users who prefer a functional approach. Not to mention it's current core usage is in one of the largest OOP-library ecosystems around.

---

<div class="post-metadata">

**Author:** ![Mordil](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mordil/32/5840_2.png) [@Mordil](https://forums.swift.org/u/Mordil)\
**Post date:** [December 19, 2019, 7:02pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/58 "2019-12-19T19:02:50Z")

</div>

One of the things that I was hoping to see is an extension of [Compiler Diagnostics (SE-1096)](https://github.com/apple/swift-evolution/blob/master/proposals/0196-diagnostic-directives.md) within a particular compile path.

What I mean is more akin to the `constexpr if` type of thing in C++, where if we have:

In the example above with `abstractMethod` invoked in the base implementation that simply calls `fatalError`, instead you would just put an `#error(...)` in the base implementation.

During compilation, if the compiler detects that the base implementation is invoked, it will trigger the compile error.

---

<div class="post-metadata">

**Author:** ![Ilias\_Karim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ilias_karim/32/2339_2.png) [@Ilias\_Karim](https://forums.swift.org/u/Ilias_Karim)\
**Post date:** [December 20, 2019, 4:05pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/59 "2019-12-20T16:05:21Z")

</div>

Right, Swift specifically supports OOP use cases like abstract classes with its `fatalError` function.

---

<div class="post-metadata">

**Author:** ![Ilias\_Karim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ilias_karim/32/2339_2.png) [@Ilias\_Karim](https://forums.swift.org/u/Ilias_Karim)\
**Post date:** [December 20, 2019, 4:20pm UTC](https://forums.swift.org/t/abstract-class-in-swift/26168/60 "2019-12-20T16:20:30Z")

</div>

> Yeah, that's just religion.

Judaism, Christianity, and Islam are religion. This is dialectic. Dismiss it at your peril.

[Previous page](https://forums.swift.org/t/abstract-class-in-swift/26168.md?page=2)

[Next page](https://forums.swift.org/t/abstract-class-in-swift/26168.md?page=4)
