1

“ For class instances, a constant property can be modified during initialization only by the class that introduces it. It cannot be modified by a subclass.” Excerpt From: Apple Inc. “The Swift Programming Language (Swift 3.1).” iBooks.

I am having difficulty in understanding this, Since i am able to modify the property by a subclass also. Below is the code.

class ConstantTest {
    let constant: String
    init(constant: String) {
        self.constant = constant
    }
    func printConstant() {
        print(constant)
    }
}

let constanttest = ConstantTest(constant: "Hello")
constanttest.printConstant()

class SubConstClass: ConstantTest { }

var subTest = SubConstClass(constant: "hey")
subTest.printConstant()
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • 2
    This subclass doesn't modify the value. The `init` is in the superclass. (Note that classes should have a leading capital; it's difficult to read your example.) – Rob Napier Mar 14 '17 at 20:56
  • @RobNapier Sorry for the trouble, –  Mar 14 '17 at 21:14

3 Answers3

4

The key to your confusion is what it means for a subclass to initialize a constant property. This means that a subclass cannot introduce an initializer that assigns the value. Let's consider a simple case:

class Person {
    let name: String
    init() {
        name = "Alice"
    }
}

This could be more simply written by assigning name in its declaration, but I'm hoping this is clearer. Now we want to create a subclass that assigns name to something else. The obvious way to do this (and how you'd do it in languages that don't have constant properties) would be to assign it after calling super.init():

class Employee: Person {
    override init() {
        super.init()
        name = "Bob" // error: cannot assign to property: 'name' is a 'let' constant
    }
}

Nope. We run into exactly the case described in your excerpt. Well, maybe we should assign it first?

class Employee: Person {
    override init() {
        name = "Bob" // error: cannot assign to property: 'name' is a 'let' constant
        super.init()
    }
}

Nope. No better.

Ah! It's because we call super.init(). Let's just not call it.

class Employee: Person {
    override init() {
        name = "Bob" // error: cannot assign to property: 'name' is a 'let' constant
    }
}

No... When they say you can't do this, they mean you can't do this. You can explore more, for instance changing the class to:

class Person {
    let name = "Alice"
}

And you'll find you have all the same problems. You cannot assign to a let constant in a superclass from a method introduced in a subclass.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
1

You are not modifying existing constants in your code - only creating new instances of your class. If you want to see an error to prove it, try this:

let constanttest = ConstantTest(constant: "Hello")
constanttest.constant = "World" //Will not compile because "constant" is a constant

As an example for the bit about it not being able to be modified by a subclass:

class ConstantTest {

    let constant: String //<--- This is the constant you are unable to change
    init(constant: String) {
        self.constant = constant
    }

    func printConstant() {
        print(constant)
    }
}

let constantTest = ConstantTest(constant: "Hello")
constantTest.printConstant()
constantTest.constant = "World" //Will not compile

class SubConstClass: ConstantTest { }

let subTest = SubConstClass(constant: "hey")
subTest.printConstant()
subTest.constant = "Hi" //Will not compile (same as superclass)

In case you are confused about the instantiation of these classes, here is another simple example of var and let using String:

let constantString = "constant"
var mutableString = "mutable"

constantString = "oops" //Will not compile
mutableString = "changed" //Totally fine, since this is a var
creeperspeak
  • 5,403
  • 1
  • 17
  • 38
  • 1
    I changed the let constant to var and tried running the below code, it ran successfully and even i was able to modify the property with subclass also. please find the example below :- –  Mar 14 '17 at 21:24
  • Again, you are not modifying properties in your code - you are simply creating new `ConstantTest` instances. These are the same _type_, but are different instances. As for the subclass - same thing. You are creating a new instance of the subclass, and are never modifying any properties once they are initialized. – creeperspeak Mar 14 '17 at 21:30
  • 1
    i am very sorry, i am not able to paste my code properly –  Mar 14 '17 at 21:34
  • It's ok - I can see what you're doing. I think you're still misunderstanding though - now you have made `constant` a `var` instead of a `let`. That means that is is _not_ a constant, so you are able to modify it, which is why you're able to set it to "Hii". If you create a constant with `let` it means that you can't assign a new value to that constant. – creeperspeak Mar 14 '17 at 21:37
  • 1
    ohh my mistake, is it possible to explain ("For class instances, a constant property can be modified during initialization only by the class that introduces it. It cannot be modified by a subclass.") via example. –  Mar 14 '17 at 21:47
  • I added more examples. Hopefully this helps? – creeperspeak Mar 14 '17 at 21:56
1

I just think the other answer haven't understood your confusion. , though creeperspeak commented you here. You seem not to understand the difference between a class and its instances:

See here and here

And then the examples below:

let constanttest1 = ConstantTest(constant: "Hello") // This is an INSTANCE of ConstantTest class
let constanttest2 = ConstantTest(constant: "Hi") // ANOTHHER INSTANCE
let constanttest3 = ConstantTest(constant: "Bye") // another instance
let constanttest4 = ConstantTest(constant: "ByeBye") // another instance

var subTest = SubConstClass(constant: "hey") // This is an an instance of SubConstClass
var subTest2 = SubConstClass(constant: "heyhey") // This is an an instance of SubConstClass
var subTest3 = SubConstClass(constant: "HaHaHa") // This is an an instance of SubConstClass.

None of the instances conflict with each other.

Community
  • 1
  • 1
mfaani
  • 33,269
  • 19
  • 164
  • 293