I have a situation where I need to override the getter of a property.
Let's say we have:
public class MyBaseClass { private var _name: String public internal(set) var name: String { get { return self._name } set { self._name = newValue } } }
Nothing really fancy, I guess.
Now, if I try to override the getter in a derived class:
public class MyDerivedClass: MyBaseClass { public var name: String { get { return "Derived - \(super.name)" } } }
I get the compile error: Cannot override mutable property with read-only property 'name'.
If I try to add the setter and overriding it:
public class MyDerivedClass: MyBaseClass { public internal(set) var name: String { get { return "Derived - \(super.name)" } set { super.name = newValue } } }
I get the error: Setter of overriding var must be as accessible as the declaration it overrides.
And if I try the following:
public class MyDerivedClass: MyBaseClass { public internal(set) var name: String { get { return "Derived - \(super.name)" } } }
Then, the compiler crashes...
How can I achieve to override only the getter ?
Swift version: 5.6. The override is used when you want to write your own method to replace an existing one in a parent class. It's used commonly when you're working with UIViewControllers , because view controllers already come with lots of methods like viewDidLoad() and viewWillAppear() .
Hi, Swift rules state that any inherited property can be overridden whether it is implemented as a stored or computed property at source (parent class).
In Swift Inheritance, the subclass inherits the methods and properties of the superclass. This allows subclasses to directly access the superclass members. Now, if the same method is defined in both the superclass and the subclass, then the method of the subclass class overrides the method of the superclass.
Preventing Overrides You can prevent a method, property, or subscript from being overridden by marking it as final. Do this by writing the final modifier before the method, property, or subscript's introducer keyword (such as final var , final func , final class func , and final subscript ).
This works for me:
public class MyBaseClass { private var _name: String = "Hi" public internal(set) var name: String { get { return self._name } set { self._name = newValue } } } public class MyDerivedClass:MyBaseClass { override public var name: String { get { return "Derived - \(super.name)" } set { super._name = newValue } } } MyDerivedClass().name
EDIT
This code works for me in a playground, placing it in the Sources -> SupportCode.swift file
public class MyBaseClass { private var _name: String = "Hi" public internal(set) var name: String { get { return self._name } set { self._name = newValue } } public init() { } } public class MyDerivedClass:MyBaseClass { override public var name: String { get { return "Derived - \(super.name)" } set { // do nothing } } public override init() { } }
It's a bit of a bodge because I get the same warning as you that internal(set)
cannot be placed before the overridden subclass variable. It may well be a bug. And also I'm cheating to make sure the setter of the derived class does nothing.
A more common use of internal(set)
or private(set)
is to have code like this, which is similar to that in the documentation:
public class MyBaseClass { public private(set) var _name: String = "Hi" public var name: String { get { return self._name } set { self._name = newValue } } public init() { } } public class MyDerivedClass:MyBaseClass { override public var name: String { get { return "Derived - \(super.name)" } set { super._name = newValue } } public override init() { } }
Here the setter can be read directly with MyDerivedClass()._name
but it cannot be altered, e.g. this MyDerivedClass()._name = "Fred"
would raise an error but MyDerivedClass().name = "Fred"
would be OK.
MyBaseClass does not compile because:
So first of all we need to add a proper initializer to MyBaseClass
public class MyBaseClass { private var _name: String public internal(set) var name: String { get { return self._name } set { self._name = newValue } } init(name : String){ _name = name } }
Now we can declare MyDerivedClass
that overrides the computed property:
Here's the code:
public class MyDerivedClass: MyBaseClass { public override var name: String { get { return "Derived - \(super.name)" } set { super.name = newValue } } }
From my playground:
let somethingWithAName = MyDerivedClass(name: "default name") println(somethingWithAName.name) // > "Derived - default name" somethingWithAName.name = "another name" println(somethingWithAName.name) // > "Derived - another name"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With