-2

I don't understand why the following code works. Isn't STEALTH being redefined in the subclass... although it is declared as const in the parent? FYI, I was under the impression that const prevents the variable from being redefined!

  class Person {
    const STEALTH = "MINIMUM";
  }

  class Ninja extends Person {          
    const STEALTH = "MAXIMUM";
  }

  echo Ninja::STEALTH; // prints out 'MAXIMUM'

Please note that I am not asking about the scope resolution operator. I think I understand the difference between printing out Ninja::STEALTH vs Person::STEALTH. I am just surprised at the fact that ninja is able to inherit a const variable and yet have the ability to redefine it!

Grateful
  • 9,685
  • 10
  • 45
  • 77
  • 1
    Possible duplicate of [Overriding class constants vs properties](https://stackoverflow.com/questions/13613594/overriding-class-constants-vs-properties) – mingos Jul 11 '17 at 09:39
  • 2
    Who said it is redefined? – u_mulder Jul 11 '17 at 09:40
  • 5
    `Person::STEALTH` and `Ninja::STEALTH` are clearly two different things… – deceze Jul 11 '17 at 09:42
  • @deceze Yes, I can see that. I am not asking about the scope resolution operator. I am surprised at the fact that ninja is inheriting person and yet able to redefine `STEALTH`. – Grateful Jul 11 '17 at 09:43
  • 1
    There's __no__ redefining here. You have __two__ different constants. – u_mulder Jul 11 '17 at 09:44
  • @u_mulder But then if I don't have that "second" constant redefinition... and `echo Ninja::STEALTH`, I would be able to print out the parent's value `MINIMUM`? It seems like the value IS being inherited.. and if that is the case, then why I am able to define a NEW constant with the SAME name of a constant that already exists via inheritance? Normally, I understand overriding... but in this case, how am I able to override a `const` variable? – Grateful Jul 12 '17 at 02:09
  • Stop thinking in `values`, think in `items`. You have `item` of type `constant` in class `Person`. As class `Ninja` inherits class `Person`, class `Ninja` knows about every `item` (which is not private) of parent class. So, class `Ninja` knows about `item` of type `constant`. Now, you define new `item` of type `constant` with same name in class `Ninja`. So you have __two__ items: one `item` from parent class and second `item` in `Ninja` itself. – u_mulder Jul 12 '17 at 06:56

2 Answers2

1

I was under the impression that const prevents the variable from being redefined!

const prevents the value to be modified.

It is not possible to define two different objects that has the same name using define(). It is also not possible to define two different objects that has the same name using const. A const class member is always accessed using its full name (class name + :: + constant name).

The name of the STEALTH constant defined by the Person class is Person::STEALTH. The Ninja class declares the constant Ninja::STEALTH.

They are different objects.

const (and static) class properties are not inherited the same way instance properties are. If a const property defined by the base class is not masked by another object with the same name defined by the child class, the base class const property is copied in the child class and can be accessed using the child class name.

For example:

class Person {
    const STEALTH = "MINIMUM";
}

class Citizen extends Person {

}

class Ninja extends Person {          
    const STEALTH = "MAXIMUM";
}

echo Person::STEALTH;    // prints out 'MINIMUM'
echo Citizen::STEALTH;   // prints out 'MINIMUM'; same as Person::STEALTH 
echo Ninja::STEALTH;     // prints out 'MAXIMUM'

Because class Citizen extends class Person and it doesn't define its own STEALTH constant, Citizen::STEALTH is a copy of Person::STEALTH1.

Class constants are global objects with fancy names (and class visibility modifiers since PHP 7.0).

axiac
  • 68,258
  • 9
  • 99
  • 134
  • Okay... that makes more sense to me now! Thank you! – Grateful Jul 11 '17 at 09:47
  • It seems `const` variables ARE inherited. I commented out `const STEALTH = "MAXIMUM";` in the Ninja class.. and was still able to print out `Ninja::STEALTH`. It printed the inherited value of `MINIMUM`.... I am confused all over again! – Grateful Jul 12 '17 at 02:13
  • Indeed, both `const` and `static` class properties of the base class can be accessed from the child class using the name of the child class. From this point of view, they are inherited. What I meant is that `Ninja::STEALTH` is the same object as `Person::STEALTH` and not a copy. This is troublesome on `static` properties (not that troublesome on `const` because they cannot be changed). I guess I will reformulate the answer. – axiac Jul 12 '17 at 06:08
1

const merely means that the value cannot be altered at runtime. It does not restrict classes from independently defining a constant by the same name; the only thing is that inheritance rules will define when and how the parent's value may get shadowed by the child's.

deceze
  • 510,633
  • 85
  • 743
  • 889