Reputation: 17725
Question:
Is there a way to prevent a class instance (reference type) from being modified ?
Reason:
The reason for asking this is because when a reference to a class instance is passed to a function, the function might unintentionally modify the instance.
Note: Using let or private function / property prevents complete access to the outside world. The question is how to prevent a normal class instance from being modified by a function.
I was hoping for something like what is available in C++.
C++ code equivalent of what I was requesting:
const CA * ca1; //This is C++ and was hoping for something like this in swift
Code:
class CA {
var x1 : Int = 10
func modify() {
x1 = 99
}
}
let ca1 = CA()
ca1.x1 = 30 //Is there a way I can prevent ca1 from this from being modified ?
ca1.modify() //Is there a way I can prevent ca1 from this from being modified ?
//This function should not modify the CA instance
func display(#ca : CA) {
ca.x1 = 30 //Is there a way I can prevent ca from this from being modified ?
ca.modify() //Is there a way I can prevent ca from this from being modified ?
println("ca.x1 = \(ca.x1)")
}
Upvotes: 1
Views: 1854
Reputation: 92384
You can make the property have an internal (the default access) getter and private setter. This way, other classes can read the value but they cannot modify it, only your class can modify it.
class Test {
private(set) var x1 : Int = 0
func increaseX1() {
x1++
}
}
let t = Test()
print(t.x1) // 0
t.increaseX1()
print(t.x1) // 1
t.x1 = 2 // error: Cannot assign to 'x1' in 't'
Note that you will be able to assign t.x1
if you try this in the playground since "private" isn't totally private in Swift: code within the same source file can access it.
To make the getter public instead of internal, you'd do:
public private(set) var x1 : Int = 0
// or:
private(set) public var x1 : Int = 0
Edit: Now that I understand your intention, here's one way to work around the problem that Swift doesn't support the const
mechanism of making objects read-only in the way C++ does: create a helper struct that only has let
constants and provide a function that returns such an helper. I'd only use that with classes that have only few instance variables, though (you wouldn't want to do that with a class that has dozens):
struct ConstCA {
let x1 : Int
}
class CA {
var x1 : Int = 10
func modify() {
x1 = 99
}
func getConstCA() -> ConstCA {
return ConstCA(x1 : x1)
}
}
func display(#ca : ConstCA) {
// Can only read `x1` but cannot modify it.
}
Upvotes: 3
Reputation: 1714
class CA {
If you make the var
a let
then neither modify()
can change it.
let x1: Int = 10 // wrong, can't be modified neither internally.
Correct solution would be to make x1
private
, now you can access it only from here. If you try to access x1
elsewhere in the project you'll get the error: 'CA' does not have a member named 'x1'
private var x1: Int = 10 // correct, class objects can change it, instances can not.
func modify() {
x1 = 99
}
}
If you don't want to access neither the modify()
function from your class instance variable, just private
that too.
Also for your reference I find that this article explains Access Control in a very concise and simple way: Access Control in Swift
Upvotes: 1
Reputation: 4533
You can always use let to create constant that cannot be modified
let x1 : Int = 10
or you can implement it with getter:
var x1 : Int {
get {
return 10
}
}
By using this you'll be able to access getter only and thus you'll not be able to modify variable.
Upvotes: 0