Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Achieving the effect of a sealed class in Swift

I'm trying to achieve the effect of Kotlin sealed class in Swift, so that I can implement a class-based alternative to enums with associated types.

The following results in a compiler error:

final class Foo {
    class Bar: Foo {}  // Error: inheritance from a final class "Foo"
}

Is there a way to effectively "seal" a Swift class from further subclassing but still allow subclassing in the first place?

like image 379
Peter Alfvin Avatar asked Jan 02 '17 16:01

Peter Alfvin


People also ask

What is sealed class in Swift?

‍ Sealed classes are abstract classes and you can define their child classes only in the same file. User's won't be able to create their implementation of our sealed class, exactly as we want. This also makes the compiler know the exact set of descendants of our sealed class. In Swift - enums.

Can we override sealed class?

You can't inherit from a sealed class, so no inheritance, no override. The override modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event. When applied to a class, the sealed modifier prevents other classes from inheriting from it.

What is the advantage of sealed class?

Sealed classes prevent derivation. Because they can never be used as a base class, some run-time optimizations can make calling sealed class members slightly faster.

Are Sealed classes faster?

sealed classes will be at least a tiny bit faster, but sometimes can be waayyy faster... if the JIT Optimizer can inline calls that would have otherwise been virtual calls. So, where there's oft-called methods that are small enough to be inlined, definitely consider sealing the class.


1 Answers

I would give a look at this Using Kotlin’s sealed class to approximate Swift’s enum with associated data and (mostly) this Swift Enumerations Docs

Kotlin:

sealed class Barcode {
   class upc(val numberSystem: Int, val manufacturer: Int, val product: Int, val check: Int) : Barcode()
   class qrCode(val productCode: String) : Barcode()
}

and then:

fun barcodeAsString(barcode: Barcode): String =
   when (barcode) {
      is Barcode.upc -> “${barcode.numberSystem} ${barcode.manufacturer} 
   ${barcode.product} ${barcode.check}”
      is Barcode.qrCode -> “${barcode.productCode}”
}

While in Swift:

enum Barcode {
   case upc(Int, Int, Int, Int)
   case qrCode(String)
}

And then do things like:

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("SDFGHJKLYFF")

or:

switch productBarcode {
case .upcA(let a, let b, let c, let d):
    print("UPC: \(a),\(b),\(c),\(d)")
case .qrCode(let code):
    print("QR Code: \(code)")
}
like image 92
inigo333 Avatar answered Sep 22 '22 12:09

inigo333