I posted this question originally on StackOverflow but it doesn't seem to be a feature yet supported by Swift 3, so I am reposting my question here.
I am aware of `private(set)` as discussed here and here and here but it doesn't seem to work for my situation where I have class-type instance property.
I have an instance property where I would like it to have read-only access. The following code shows some concrete example.
class Point {
var x: Int
var y: Int
init(_ x: Int, _ y: Int) {
self.x = x
self.y = y
}
}
class Sprite {
private(set) var origin = Point(0,0)
func incrementX() {
origin.x += 1
}
func incrementY() {
origin.y += 1
}
}
Here, my intent is to make `Sprite` the sole owner of `Point`, allowing it to be the only one who can modify `origin`, otherwise making `origin` read-only to the public. However:
var sprite = Sprite()
sprite.origin = Point(100, 200) // Error: setter is inaccessibie. Expected behavior.
sprite.origin.x = 150 // No error. The origin.x will be set to 150.
Apparently I can still modify `origin` by modifying internal `x` and `y` directly, but this is not my intent.
How do I make `origin` truly read-only? Am I missing something?
Modifying `Point` to `private var x: Int` or `fileprivate var x: Int` won't work for me because I want to be able to let an external class like `Sprite` modify `Point`.
Note1: (Since someone on SO asked why I didn't use `CGPoint`) The code serves as as example to make my question more concrete. I actually have a complex class as instance property in another class, not this simple `Point`. I also can't use it as `struct` due to other design constraints.
Note2: An answer in SO points out that you cannot prevent the reference from being mutable. That's a limitation in Swift I just learned, because apparently, I can achieve exactly what I wanted in C++ using `Point const &`:
class Point {
public:
int x;
int y;
Point(int _x, int _y) {
x = _x;
y = _y;
}
Point & operator=(const Point & rhs) {
x = rhs.x;
y = rhs.y;
return *this;
}
...
};
class Sprite {
Point origin;
public:
Sprite()
: origin(0,0)
{}
// HERE
Point const & getOrigin() const { return origin; }
void incrementX() { origin.x += 1; }
void incrementY() { origin.y += 1; }
};
int main(int argc, const char * argv[]) {
Sprite sprite = Sprite();
Point const & o = sprite.getOrigin();
cout << "o: " << o << endl; // (0,0)
// o.x = 10; // Error: Cannot assign to const-qualified type.
// o = Point (100, 200); // Error: no viable overlaod =.
sprite.incrementX();
cout << "o: " << o << endl; // (1,0). Swift can't get this behavior with `struct Point`, but it won't prevent some writing attempts with `class Point`.
cout << "sprite.origin: " << sprite.getOrigin() << endl; // (1,0).
return 0;
}