Home > Enterprise >  Downcast generic class
Downcast generic class

Time:06-29

I've got a generic class based on some type, and a child class which specifies that type. However, the Swift compiler doesn't seem to be able to downcast the parent class with the correct type to the child class.
I'm surprised because it seems like a legitimate need.

For example

class MyClass<T> {}

class ChildClass: MyClass<Double> {}

func test() {
  let instance = MyClass<Double>()
  let castedInstance: ChildClass = instance as! ChildClass
}

This code throws a runtime error: Could not cast value of type 'MyClass<Swift.Double>' (0x1f3e449f0) to 'ChildClass' (0x1024f58b0).

Is there any way to cast it the right way, or is it forbidden for some reason ? Anything I misunderstood ?


Edit : I understand that casting is impossible. What is the best way to instanciate a ChildClass from a MyClass<Double> then ?

  1. use a simple typealias ChildClass = MyClass<Double> (obviously misnamed now). I could implement specific behavior with an extension
extension MyClass<T> where T == Double {
  func specificFunction() {}
}
  1. or have a ChildClass initializer init(_ instance: MyClass<Double>). However that requires me to create the instance myself everytime
let child = ChildClass(from: functionThatReturnsAMyClass())

or any other way ?

CodePudding user response:

It seems you have a misunderstanding of how inheritance works. You cannot convert the type of an object using type casting, whether that's up- or down casting.

You can only use downcasting when the object you are trying to cast is declared/stored as a more general type (a parent class for instance), but it might hold a more specialised instance (subclass). However, you are declaring a parent instance and then trying to downcast it to a subclass. That can never work, since the instance is of a different type.

Your example works if you declare a variable of the parent class type, but assign a child class instance to it.

func test() {
  let instance: MyClass<Double> = ChildClass()
  let castedInstance: ChildClass = instance as! ChildClass
}

CodePudding user response:

I'd say you misunderstand what casting is. Casting reveals to the compiler what something actually is. It does not change what that thing is.

So you cannot cast instance to ChildClass, for the simple reason that it is not in fact a ChildClass.

  • Related