Reputation: 790
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 ?
Upvotes: 33
Views: 32676
Reputation: 5906
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.
Upvotes: 31
Reputation: 59506
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"
Upvotes: 7