steventnorris
steventnorris

Reputation: 5896

Self property in parent class not working

I have a parent class with a method signature like this:

class MyParent {
  func doStuff(property: Self) {
    fatalError("Not Implemented")
  }
}

I then inherit form it like so:

final class MyInherited: MyParent {
  var arbitraryVal:String = "Hello"
  override func doStuff(property: MyInherited) {
    self.arbitraryVal = property.arbitraryVal
  }
}

However, it says that doStuff doesn't override any method from its superclass. Is there a way to do what I'm trying to do here and have a parent class required a method property be of type Self?

Upvotes: 0

Views: 313

Answers (2)

Rob Napier
Rob Napier

Reputation: 299565

This violates LSP. Anything the superclass can do, the subclass must also be able to do. If MyParent.doStuff can accept a MyParent, then MyInherited.doStuff must also be able to accept a MyParent. Otherwise, if you passed this object to a function that accepted a MyParent, how would it type-check a later call to doStuff?

A subclass can restrict what it returns, but it cannot restrict what it accepts. So it's ok for the output of doStuff to be Self, but it's not possible for the input to be Self. The input has to be at least as permissive as its parent.

I would expect that you're receiving an error in MyParent, not just MyInherited. It should say:

Covariant 'Self' can only appear as the type of a property, subscript or method result; did you mean 'MyParent'?

And this is correct. It's not possible to restrict a parameter to a smaller set of values. This isn't a Swift limitation. This is a limitation of any sound type system that includes inheritance.

Upvotes: 1

Joakim Danielson
Joakim Danielson

Reputation: 52043

You can use a protocol instead of a superclass

protocol MyParent {
    var arbitraryVal: String { get set }
    func doStuff(property: MyParent)
}

Upvotes: 1

Related Questions