# Instance-level polymorphism

**URL:** <https://forums.swift.org/t/instance-level-polymorphism/30087>\
**Category:** Discussion\
**Created:** [October 22, 2019, 7:53pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087 "2019-10-22T19:53:50Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 22, 2019, 7:53pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/1 "2019-10-22T19:53:50Z")

</div>

I've seen some similar ideas discussed on the forums (notably [Polymorphic methods in enums](https://forums.swift.org/t/polymorphic-methods-in-enums/15093)) which are focused around the idea of improving the experience of attaching `case`-specific behavior to `enum`s without having a totally fragmented implementation. I encountered this issue yet again yesterday and wanted to solicit feedback on some thoughts I had about potential solutions.

# Motivation

It is a common pattern to allow a type to take on one of a limited set of values defined ahead of time by the type implementer. In the simplest case, an `enum` is well suited to model this behavior. To borrow the example from the linked thread:

```swift
enum TrafficLight {
    case red
    case yellow
    case green
}

```

Since `enum`s allow the specification of methods and computed variables, we can easily add simple behavior to this `enum` that depends on the current `case`:

```swift
enum TrafficLight {
    case red, yellow, green

    var canAdvance: Bool {
        switch self {
        case .green: 
            return true
        default:
            return false
        }
    }
}

```

However, this approach doesn't scale super well. Adding a `flashingRed` or `flashingYellow` state would require us to add additional `case` statements to every method and computed variable, and if any of them have `default` statements then the compiler will not catch us if we forget to edit one of the methods. This sort of construct also suffers from readability—there's no way for me as a client of the `TrafficLight` type to see all of the behavior associated with a specific `case` (perhaps we added `color`, `luminosity`, `displayDuration` computed variables as well...). Instead, I have to visit each member and work out where exactly the `case` in question falls in the `switch` statement.

# Existing Solutions

## Private `init` structs

One solution that exists today is to define `TrafficLight` as a `struct` with a private initializer:

```swift
struct TrafficLight {
    let canAdvance: Bool
    let color: UIColor
    let luminosity: Double

    private init(canAdvance: Bool, color: UIColor, luminosity: Double) { ... }

    static let red = TrafficLight(canAdvance: false, color: .red, luminosity: 0.9)
    static let yellow = TrafficLight(canAdvance: false, color: .yellow, luminosity: 10)
    static let green = TrafficLight(canAdvance: true, color: .green, luminosity: 0.75)
}

```

With a suitably verbose implementation, we can even create methods on `TrafficLight` that can reference "`self`":

```swift
struct TrafficLight {
    ...
    private let _allowsVehicleThrough: (TrafficLight, Vehicle) -> Bool = { _self, vehicle in 
        return _self.canAdvance
    }

    func allowsVehicleThrough(_ vehicle: Vehicle) -> Bool {
        return self._allowsVehicleThrough(self, vehicle)
    }

    static let red = TrafficLight(
        canAdvance: false,
        color: .red,
        luminosity: 0.9,
        _allowsVehicleThrough: { _, vehicle in
            return vehicle.isEmergencyVehicle
        }
    )
    ...
}

```

A `struct` can also leverage stored properties, so that each traffic light could have an associated `intersectionId` (and `static let red = ...` would become `static func red(withIntersectionId: Int) -> TrafficLight`), which on an `enum` would necessitate adding an associated value to each individual `case`.

This solution, however, results in a large amount of boilerplate in order to support the same functionality as the `enum` based approach, and requires difficult-to-name private members that make the code difficult to understand, so the readability benefits of specifying instance behavior inline are questionable.

## Protocols

When modeling more complex behavior like this, it might make sense to model a `TrafficLight` as a `protocol`, which guarantees accessors for `canAdvance`, `color`, etc. Then, implementations would be declared as `struct RedLight: TrafficLight`, and appropriate implementations can be provided.

This solution falls short for a few different reasons. It provides no way for the author of `TrafficLight` to enforce the fact that `TrafficLight` should only be conformed to by a specific set of types (see [Constrain protocol usage outside the module](https://forums.swift.org/t/constrain-protocol-usage-outside-the-module/8832)). Furthermore, it introduces a conflation of instances and types. Under `protocol TrafficLight`, `var x = RedLight()` and `var y = RedLight()` aren't meaningfully different but could exhibit different behavior, counter to the intention of the author of `TrafficLight`. Some of these problems could be mitigated by marking the requirements of `TrafficLight` as static, and then accepting arguments of type `TrafficLight.Type` everywhere, but this introduces further issues that arise when dealing with metatypes (notably, lack of protocol conformance).

# Proposed Solutions

## Lower friction for the "switch on `self`" pattern

One solution discussed in the thread linked at the beginning of this post is to introduce syntax which would act as an implicit `switch` over some portion of a method on an `enum` (either `self` or the arguments). Under this proposal, we might write:

```swift
var canAdvance: Bool {
case .green:
    return true
default:
    return false
}

```

This reduces some boilerplate, but ultimately does not solve many of the issues with the `switch`-based solution that exists today. The implementation for a specific `case` is still split apart the entire type in ways that may be non-trivial to verify, and adding a new case requires touching every existing method.

## Explicit instance-level polymorphism

**For `struct`s**

We could also add an explicit syntax for supporting instance-level polymorphism, which allows a type to specify inline that instances may (or must) define implementations for methods as they see fit. This would essentially act as sugar for the `struct` based approach mentioned above, with a straw man syntax as something like:

```swift
struct TrafficLight {
    var canAdvance: Bool
    @instanceFunc func allowsVehicleThrough(_ vehicle: Vehicle) -> Bool {
        // default implementation
    }

    private init(canAdvance: Bool, func allowsVehicleThrough: @instanceFunc (Vehicle) -> Bool) {
        self.canAdvance = canAdvance
        self.allowsVehicleThrough = allowsVehicleThrough
    }

    static let red = TrafficLight(
        canAdvance: false,
        allowsVehicleThrough: { vehicle in 
            // 'self' is available here since TrafficLight accepts an 
            // @instanceFunc for this parameter, refers to this specific
            // instance of TrafficLight.
            return self.canAdvance || vehicle.isEmergencyVehicle
        }
    )
}

```

**For `enum`s**

Also proposed in the thread linked at the top is some sort of syntax for separating out method implementations by `case`. This usually looked something like:

```swift
enum TrafficLight {
    case red, yellow

    // default implementation
    var canAdvance: Bool {
        return false
    }

    case green

    var canAdvance: Bool where self == .green {
        return true
    }
}

```

or

```swift
enum TrafficLight {
    var canAdvance: Bool // implementation provided by cases

    case red {
        var canAdvance: Bool { return false }
    }

    case yellow {
        var canAdvance: Bool { return false }
    }

    case green {
        var canAdvance: Bool { return true }
    }
}

```

This solution, like the `init`-based one, successfully separates implementation by instance, and in the first case it reuses existing `where` syntax in a way that is relatively apparent what it means.

## "Closed" protocols

Raised in the link in the **Protocols** section above, we could allow users to specify a closed protocol:

```swift
// module Traffic
closed protocol TrafficLight { ... }

// module MyApp
struct PurpleLight: TrafficLight { // error: 'PurpleLight' cannot conform to 'TrafficLight' because 'TrafficLight' is closed.
    ...
}

```

This would allow the compiler to enforce the restriction of "only these specific types may conform to this protocol." This would not enable some features that would be possible with instance-level poly morphism (e.g. it may not be possible to have `TrafficLight: Hashable`, depending on use-case).

# Other alternatives...?

The existing and proposed solutions are just what came to mind over the course of the couple days. If there are better existing tools to model this type of behavior, or if anyone else has thought of ways that Swift could provide better support for this pattern, I'd love to hear!

Suggested by @Paul_Cantrell, adapting Java syntax:

> [@Paul\_Cantrell](#):
>
> ```swift
> struct TrafficLight { 
> case red(canAdvance: false) 
> case yellow(canAdvance: false) 
> case green(canAdvance: true) 
> 
> let canAdvance: Bool 
> }
> 
> ```

Something like Kotlin's sealed class, via @GetSwifty:

> [@GetSwifty](#):
>
> This reminds me a lot of one way kotlin's [sealed class](https://kotlinlang.org/docs/reference/sealed-classes.html) can be used.
> 
> ```swift
> sealed class StopLight(val canAdvance: Boolean) {
> class Red: StopLight(canAdvance: false)
> class Yellow: StopLight(canAdvance: false)
> class Green: StopLight(canAdvance: true)
> }
> val myLight = StopLight.Red
> val canAdvance = myLight.canAdvance
> 
> ```

---

<div class="post-metadata">

**Author:** ![Paul\_Cantrell](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/paul_cantrell/32/16764_2.png) [@Paul\_Cantrell](https://forums.swift.org/u/Paul_Cantrell)\
**Post date:** [October 22, 2019, 8:00pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/2 "2019-10-22T20:00:56Z")

</div>

Java enums have both this (transposed to Swift syntax):

```
struct TrafficLight {
    case red(canAdvance: false)
    case yellow(canAdvance: false)
    case green(canAdvance: true)

    let canAdvance: Bool
}

```

…and this:

> [@Jumhyn](#):
>
> ```swift
> enum TrafficLight {
> var canAdvance: Bool // implementation provided by cases
> 
> case red {
> var canAdvance: Bool { return false }
> }
> 
> case yellow {
> var canAdvance: Bool { return false }
> }
> 
> case green {
> var canAdvance: Bool { return true }
> }
> }
> 
> ```

They’re nice features, and I miss them in Swift.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 22, 2019, 8:05pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/3 "2019-10-22T20:05:37Z")

</div>

That's cool, I like the idea of adding `case`s to `struct`s. It makes the intention clearer that the struct is meant to take on one of a limited set of values, rather than searching and searching for an `init` and coming up empty handed.

---

<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:** [October 22, 2019, 9:15pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/4 "2019-10-22T21:15:37Z")

</div>

Making this easier would definitely be great!

This reminds me a lot of one way kotlin's [sealed class](https://kotlinlang.org/docs/reference/sealed-classes.html) can be used.

```swift
sealed class StopLight(val canAdvance: Boolean) {
    class Red: StopLight(canAdvance: false)
    class Yellow: StopLight(canAdvance: false)
    class Green: StopLight(canAdvance: true)
}
val myLight = StopLight.Red
val canAdvance = myLight.canAdvance

```

I think my preferred implementation would be a combination of your proposed enum implementations.

```swift
enum TrafficLight {
    // Default implementation
    var canAdvance: Bool { false }

    case red
    case yellow
    case green {
        // Overriding the implementation
        var canAdvance: Bool { true }
    }
}

```

I'm not sure how enums are implemented, but I'm guessing this should be possible just with code generation. e.g. it could translate the above into the original enum

```swift
enum TrafficLight {
    case red, yellow, green

    var canAdvance: Bool {
        switch self {
        case .green: 
            return true
        default:
            return false
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [October 22, 2019, 9:31pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/5 "2019-10-22T21:31:22Z")

</div>

> [@Jumhyn](#):
>
> ## "Closed" protocols
> 
> Raised in the link in the **Protocols** section above, we could allow users to specify a closed protocol:
> 
> ```swift
> // module Traffic
> closed protocol TrafficLight { ... }
> 
> // module MyApp
> struct PurpleLight: TrafficLight { // error: 'PurpleLight' cannot conform to 'TrafficLight' because 'TrafficLight' is closed.
> ...
> }
> 
> ```
> 
> This would allow the compiler to enforce the restriction of "only these specific types may conform to this protocol." This would not enable some features that would be possible with instance-level poly morphism (e.g. it may not be possible to have `TrafficLight: Hashable` , depending on use-case).

I have long wanted closed protocols with support for exhaustive switch. They open up design space in ways other purely sugar features don't.

I also think a general version of implicit switch sugar (not just for enums and not just over `self`) would be an interesting feature. But if I had to choose only one it would be closed protocols.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 22, 2019, 9:37pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/6 "2019-10-22T21:37:36Z")

</div>

> [@anandabits](#):
>
> I have long wanted closed protocols with support for exhaustive switch. They open up design space in ways other purely sugar features don't.

What do you imagine we would `switch` over, and what would constitute exhaustiveness? Would it be:

```swift
let light = RedLight()

switch light {
case is RedLight: 
    print("red") 
case is GreenLight:
    print("green")
case is YellowLight:
    print("yellow")
}

```

or

```swift
let light = RedLight.self

switch light {
case RedLight.self:
    print("red")
case GreenLight.self:
    print("green")
case YellowLight.self:
    print("yellow")
}

```

?

I don't know that I'm totally sold on closed protocols _as a replacement for polymorphism on `enum`-like objects_ since it still seems to introduce confusion between type and instance identity.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [October 22, 2019, 10:14pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/7 "2019-10-22T22:14:20Z")

</div>

I think it would work exactly the same as it does today:

```swift
let light = RedLight()
switch light {
case let red as RedLight: 
    // do something knowing you have a red light
case let green as GreenLight: 
    // do something knowing you have a green light
case let yellow as YellowLight: 
    // do something knowing you have a yellow light
}

```

or:

```swift
let light = RedLight.self
switch light {
case is RedLight: 
    print("red") 
case is GreenLight:
    print("green")
case is YellowLight:
    print("yellow")
}

```

The difference from today is that currently a `default` clause is required.

> [@Jumhyn](#):
>
> I don't know that I'm totally sold on closed protocols _as a replacement for polymorphism on `enum` -like objects_ since it still seems to introduce confusion between type and instance identity.

To be honest, I'm not that interested in polymorphism-like syntax for enums. If we're going to have polymorphism over a fixed set of cases I'd like to open up the design space with closed protocols. This makes more sense to me anyway as polymorphism basically implies multiple types. With enum-based polymorphism you end up with something along the lines of inaccessible "case types" where the enum type itself is an existential anyway. If we're going to go there we should make it explicit and open up the design space.

As I also said, I think the appropriate sugar to make enum methods more convenient to write is sugar for a general and implicit top-level switch.

---

<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:** [October 22, 2019, 10:30pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/8 "2019-10-22T22:30:53Z")

</div>

> [@Jumhyn](#):
>
> I don't know that I'm totally sold on closed protocols _as a replacement for polymorphism on `enum` -like objects_ since it still seems to introduce confusion between type and instance identity.

This. We already have a powerful construct for defining an Enumerated Type, it's called `enum` 😉. It seems unnecessary to try and shoehorn enumeration-style-functionality into other Types when we can leverage the already existing work done for `enum`. In one way `enum`s _already_ have a form of polymorphism with associated values.

Regardless, the design pattern of having computed properties that switch over enum cases is something I do regularly and I've seen all over the place. Some syntactic sugar to make that pattern easier to write can only be a good thing.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 22, 2019, 10:40pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/9 "2019-10-22T22:40:28Z")

</div>

> [@anandabits](#):
>
> With enum-based polymorphism you end up with something along the lines of inaccessible "case types" where the enum type itself is an existential anyway.

You get real, tangible benefit from this, though. Since the enum type is only a pseudo-existential, the limitations of `Self`/`associatedtype` constraints don’t apply, and you can freely conform to protocols so that you can have `[EnumType: Int]`, for example. Some of this would be solved by to-do items from the Generics Manifesto, but I think there would still be benefits to having an existential-like object which is a concrete type as far as the type system is concerned.

FWIW, I still like the idea of closed protocols in general, but I think there’s room in the design space for closed protocols and polymorphic “enums,” whatever form they take.

---

<div class="post-metadata">

**Author:** ![CTMacUser](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ctmacuser/32/1802_2.png) [@CTMacUser](https://forums.swift.org/u/CTMacUser)\
**Post date:** [October 22, 2019, 10:46pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/10 "2019-10-22T22:46:59Z")

</div>

> [@Jumhyn](#):
>
> **For `enum` s**
> 
> Also proposed in the thread linked at the top is some sort of syntax for separating out method implementations by `case` .

I was about to [post](https://forums.swift.org/t/multiple-dispatch/30095) about [multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch), and your idea above sounds like the next level: [predicate dispatch](https://en.wikipedia.org/wiki/Predicate_dispatch).

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 22, 2019, 11:01pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/11 "2019-10-22T23:01:28Z")

</div>

Oh, neat! That indeed sounds like the correct name for some of the ideas proposed here 🙂

(Also, most of the solutions in this post are lifted from the linked threads, the only part I hadn’t seen before making this post was the `@instanceFunc` version for instance polymorphism on structs).

---

<div class="post-metadata">

**Author:** ![jawbroken](https://avatars.discourse-cdn.com/v4/letter/j/cc9497/32.png) [@jawbroken](https://forums.swift.org/u/jawbroken)\
**Post date:** [October 23, 2019, 10:30am UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/12 "2019-10-23T10:30:51Z")

</div>

Every single one of my enum methods and computed properties starts with `switch self`, so I would like an implicit switch feature of some kind. It's pretty hard to beat `switch self`, though, so it would have to be very lightweight to be valuable, as in your example. I don't personally care about the other aspects, like regrouping the computed property values under the individual cases. These alternatives don't seem as general or useful as an implicit switch to me, and seem to require too much fiddly new syntax and exceptional behaviour to be worthwhile.

---

<div class="post-metadata">

**Author:** ![brewsterdesigns](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/brewsterdesigns/32/9392_2.png) [@brewsterdesigns](https://forums.swift.org/u/brewsterdesigns)\
**Post date:** [October 26, 2019, 1:34am UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/13 "2019-10-26T01:34:34Z")

</div>

If tuples could conform to RawRepresentable, it might be nice to do some like this:

```
typealias TrafficLightType = (canAdvance: Bool, color: UIColor)
enum TrafficLight : TrafficLightType {
   case red = (true, .red)
   case yellow = (false, .yellow)
   case green = (true, .green)

   var canAdvance: Bool { rawValue.canAdvance }
}

```

It's similar to the java syntax but might fit in better with the existing compiler?

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 26, 2019, 3:23pm UTC](https://forums.swift.org/t/instance-level-polymorphism/30087/14 "2019-10-26T15:23:17Z")

</div>

Allowing arbitrary loads as raw values for an enum is an interesting approach to this issue. I don't love that it requires you to split the full implementation of the type into two separate types for the valid cases and the actual payload, or that you would have to define boilerplate properties/methods for every member of the payload to avoid using `rawValue` everywhere, but I agree this fits into the existing compiler machinery most closely right now in terms of not really requiring any new syntax. It could apply to nominal types as well, so that this could be done as something like:

```swift
enum TrafficLight: TrafficLight.Payload {
    struct Payload {
        let canAdvance: Bool
        let color: UIColor

        fileprivate init(_ canAdvance: Bool, _ color: UIColor) { ... }
    }

    case red = .init(false, .red)
    case yellow = .init(false, .yellow)
    case green = .init(true, .green)

    var canAdvance: Bool { rawValue.canAdvance }
}

```

At that point, though, I'd probably just want to see `case` decls in `struct` definitions directly to cut out all the boilerplate.

As far as closed `protocol`s go, one thing I would love to see from them is something akin to `allCases`—something like `ClosedProtocol.allTypes: [ClosedProtocol.Type]` that would publicly export all the accessible types which conform to `ClosedProtocol`.
