# Final variables

- Thread: https://externals.io/message/99657
- Original archive: https://news-web.php.net/php.internals/99657
- Started by David Rodrigues on 2017-06-28T16:10:51+00:00
- Messages: 18
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #99657 — David Rodrigues — 2017-06-28T16:10:51+00:00

URL: https://externals.io/message/99657#99657

Hello internals,

Java supports the "final" keyword before a variable to determines that this
variables never change it reference. If I declare a variable as "final", I
can only initialize that once, then I could not change it after (but I can
manipulate the instance, without issues).

There some special reason to PHP doesn't supports things like that?

final $number = 123;
$number = 456; // Error: you change change final variables.

final $object = new stdClass;
$object->allowed = true; // No error.

This feature make sense because it tells to dev that the variable value
could not be updated directly (new reference). Which make easy to identify
when a variable is modifiable or not.

It is valid for a RFC?

- It can uses the "final" keyword;
- It doesn't a BC;

I too think that a final variable can be useful to make some internal
improvements on language (but it could be a BC for PHP internals). I mean,
as the variable could not be modified, then it don't need be a "flexible"
type internally (I guess that it is a zval, right?).

Reference: https://github.com/kalessil/phpinspectionsea/issues/363

-- 
David Rodrigues

---

## #99658 — Kalle Sommer Nielsen — 2017-06-28T16:59:51+00:00

URL: https://externals.io/message/99657#99658 · In reply to: #99657

Hi David

2017-06-28 18:10 GMT+02:00 David Rodrigues <david.proweb@gmail.com>:
> Hello internals,
>
> Java supports the "final" keyword before a variable to determines that this
> variables never change it reference. If I declare a variable as "final", I
> can only initialize that once, then I could not change it after (but I can
> manipulate the instance, without issues).
>
> There some special reason to PHP doesn't supports things like that?

It seems like what you are looking for here is actually a constant[1].
However constants do not support non scalar types, such as array or
objects, what would really solve it on the objects side of things
would be the introduction of a "readonly" keyword or similar, like
that of C#[2]

> final $number = 123;
> $number = 456; // Error: you change change final variables.
>
> final $object = new stdClass;
> $object->allowed = true; // No error.
>
> This feature make sense because it tells to dev that the variable value
> could not be updated directly (new reference). Which make easy to identify
> when a variable is modifiable or not.
>
> It is valid for a RFC?
>
> - It can uses the "final" keyword;
> - It doesn't a BC;

Anything is usually valid for an RFC, however I think (personally)
that this should rather be an RFC for a readonly keyword if anything

> I too think that a final variable can be useful to make some internal
> improvements on language (but it could be a BC for PHP internals). I mean,
> as the variable could not be modified, then it don't need be a "flexible"
> type internally (I guess that it is a zval, right?).
>
> Reference: https://github.com/kalessil/phpinspectionsea/issues/363
>
> --
> David Rodrigues


[1] http://php.net/constants
[2] https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly

-- 
regards,

Kalle Sommer Nielsen
kalle@php.net

---

## #99659 — Niklas Keller — 2017-06-28T17:37:32+00:00

URL: https://externals.io/message/99657#99659 · In reply to: #99658

2017-06-28 18:59 GMT+02:00 Kalle Sommer Nielsen <kalle@php.net>:

> Hi David
>
> 2017-06-28 18:10 GMT+02:00 David Rodrigues <david.proweb@gmail.com>:
> > […]
> this
> > […]
> I
> > […]
> can
> > […]
>
> It seems like what you are looking for here is actually a constant[1].
> However constants do not support non scalar types, such as array or
> objects,


Arrays are supported, but not objects.

Regards, Niklas


> what would really solve it on the objects side of things
> would be the introduction of a "readonly" keyword or similar, like
> that of C#[2]
>
> > […]
> identify
> > […]
>
> Anything is usually valid for an RFC, however I think (personally)
> that this should rather be an RFC for a readonly keyword if anything
>
> > […]
> mean,
> > […]
>
>
> [1] http://php.net/constants
> [2] https://docs.microsoft.com/en-us/dotnet/csharp/language-
> reference/keywords/readonly
>
> --
> regards,
>
> Kalle Sommer Nielsen
> kalle@php.net

---

## #99661 — Kalle Sommer Nielsen — 2017-06-28T18:00:11+00:00

URL: https://externals.io/message/99657#99661 · In reply to: #99659

2017-06-28 19:37 GMT+02:00 Niklas Keller <me@kelunik.com>:
> Arrays are supported, but not objects.

Ah yes ofcourse, my apologies.


-- 
regards,

Kalle Sommer Nielsen
kalle@php.net

---

## #99664 — David Rodrigues — 2017-06-28T18:46:57+00:00

URL: https://externals.io/message/99657#99664 · In reply to: #99658

2017-06-28 13:59 GMT-03:00 Kalle Sommer Nielsen <kalle@php.net>:

> Hi David
>
> It seems like what you are looking for here is actually a constant[1].
> However constants do not support non scalar types, such as array or
> objects, what would really solve it on the objects side of things
> would be the introduction of a "readonly" keyword or similar, like
> that of C#[2]
>
​​

​Not on reality.​ :(

The "final" keyworks make a "local scope" variable value "blocked to
rewrite" after instantiate it.
Okay, it sounds like a "const", and it is, but "not as we known it".

While constants are class member (or globals), a final variable is just a
variable blocked to rewrite, and it could be initialized with a new data
content every time that the context is called (eg. a function).

For instance (note that the parameter is "final", then I can't modify the
parameter variable, but it can receives a new value each time that I call
this function):

function write(final $message) { echo $message; }
write("Hello");
write("World");
// Write "Hello World" on ouput.

Or then:

function randomNumber() {
  final $number = `mt_rand()`;
  echo $number;

  // $number = mt_rand_again(); // <-- will not be allowed!
}
randomNumber();
​ // Write "0.123"
randomNumber();
​ // Write "0.456"
​



>
> [1] http://php.net/constants
> [2] https://docs.microsoft.com/en-us/dotnet/csharp/language-
> reference/keywords/readonly
>

-- 
David Rodrigues

---

## #99665 — David Rodrigues — 2017-06-28T23:07:23+00:00

URL: https://externals.io/message/99657#99665 · In reply to: #99664

​
Walter Parker <walterp@gmail.com>
​ wrote:​
> ​
Constant may not have been the right word (or idea), but I agree with
Kalle. We should use readonly as the keyword here and not final as the
keyword. We can keep the same scoping rules so the following would work:
>​
​> function randomNumber() {
​>​
  *readonly *$number = `mt_rand()`;
​
​I agree that "readonly" is a better keyword, but we have to points here:
1. "final" is used on some language (Java, C++ I guess);
2. "final" keyword does exists on PHP with a "similar" behaviour;

If we can implements "readonly" is good too, because turn it more implicit.



2017-06-28 15:46 GMT-03:00 David Rodrigues <david.proweb@gmail.com>:

> 2017-06-28 13:59 GMT-03:00 Kalle Sommer Nielsen <kalle@php.net>:
>
> > […]
> ​​
>
> ​Not on reality.​ :(
>
> The "final" keyworks make a "local scope" variable value "blocked to
> rewrite" after instantiate it.
> Okay, it sounds like a "const", and it is, but "not as we known it".
>
> While constants are class member (or globals), a final variable is just a
> variable blocked to rewrite, and it could be initialized with a new data
> content every time that the context is called (eg. a function).
>
> For instance (note that the parameter is "final", then I can't modify the
> parameter variable, but it can receives a new value each time that I call
> this function):
>
> function write(final $message) { echo $message; }
> write("Hello");
> write("World");
> // Write "Hello World" on ouput.
>
> Or then:
>
> function randomNumber() {
>   final $number = `mt_rand()`;
>   echo $number;
>
>   // $number = mt_rand_again(); // <-- will not be allowed!
> }
> randomNumber();
> ​ // Write "0.123"
> randomNumber();
> ​ // Write "0.456"
> ​
>
>
>
> > […]
>
> --
> David Rodrigues
>



-- 
David Rodrigues

---

## #99668 — Kalle Sommer Nielsen — 2017-06-29T02:50:22+00:00

URL: https://externals.io/message/99657#99668 · In reply to: #99664

Hi

2017-06-28 20:46 GMT+02:00 David Rodrigues <david.proweb@gmail.com>:
> The "final" keyworks make a "local scope" variable value "blocked to
> rewrite" after instantiate it.
> Okay, it sounds like a "const", and it is, but "not as we known it".

I get that, but I still don't understand why you would forcefully need
it to be a variable still then if you know the value is gonna be
constant, of course besides global visibility or in iterations


-- 
regards,

Kalle Sommer Nielsen
kalle@php.net

---

## #99669 — Kalle Sommer Nielsen — 2017-06-29T02:57:12+00:00

URL: https://externals.io/message/99657#99669 · In reply to: #99665

2017-06-29 1:07 GMT+02:00 David Rodrigues <david.proweb@gmail.com>:
>   readonly $number = `mt_rand()`;
> I agree that "readonly" is a better keyword, but we have to points here:
> 1. "final" is used on some language (Java, C++ I guess);
> 2. "final" keyword does exists on PHP with a "similar" behaviour;

> If we can implements "readonly" is good too, because turn it more implicit.
True we could re-use the final keyword, but think about it this way,
we got final methods and final classes which means it cannot be
overridden/extended respectively, if the final keyword then would also
apply to variables but it would mean they could not be written to,
that would create a WTF-factor.

The readonly keyword would work for any visibility modifiers, so
inherited classes or extending classes may read a protected property,
but not modify it as well:

class A {
 protected readonly $b;

 public function __construct() {
  $this->b = 'C';
 }
}

class B extends A {
 public function read() {
  echo $this->b;
 }

 public function write() {
  $this->b = 'D';
 }
}

$b = new B;

$b->read(); // "C"
$b->write(); // <- error


-- 
regards,

Kalle Sommer Nielsen
kalle@php.net

---

## #99670 — Marco Pivetta — 2017-06-29T04:20:39+00:00

URL: https://externals.io/message/99657#99670 · In reply to: #99669

The `final` modifier would likely clash with property type definitions, if
those ever make it to the language.

Still, a few pain-points remain:

 * References to properties (you cannot reference final properties anymore,
and that is effectively a BC break for anything using reflection and
closure scope binding)
 * Arrays and resources as properties
 * Named (Factory) constructors
 * Property nullability - how do you define if a property was written to
the "last valid time" before freezing it
 * Unset properties and providing an alternative mechanism to distinguish
"uninitiated",  "undefined" and "frozen" in he event of final properties
usage, without breaking current property access semantics

This is the exact same set of problems we had with the typed properties
RFC, and which caused the RFC to fail: please take all these in
consideration while designing the feature.



> 2017-06-29 1:07 GMT+02:00 David Rodrigues <david.proweb@gmail.com>:
> > […]
>
> > […]
> implicit.
> True we could re-use the final keyword, but think about it this way,
> we got final methods and final classes which means it cannot be
> overridden/extended respectively, if the final keyword then would also
> apply to variables but it would mean they could not be written to,
> that would create a WTF-factor.
>
> The readonly keyword would work for any visibility modifiers, so
> inherited classes or extending classes may read a protected property,
> but not modify it as well:
>
> class A {
>  protected readonly $b;
>
>  public function __construct() {
>   $this->b = 'C';
>  }
> }
>
> class B extends A {
>  public function read() {
>   echo $this->b;
>  }
>
>  public function write() {
>   $this->b = 'D';
>  }
> }
>
> $b = new B;
>
> $b->read(); // "C"
> $b->write(); // <- error
>
>
> --
> regards,
>
> Kalle Sommer Nielsen
> kalle@php.net

---

## #99672 — lists@rhsoft.net — 2017-06-29T09:04:48+00:00

URL: https://externals.io/message/99657#99672 · In reply to: #99668

Am 29.06.2017 um 04:50 schrieb Kalle Sommer Nielsen:
> 2017-06-28 20:46 GMT+02:00 David Rodrigues <david.proweb@gmail.com>:
> > […]
> 
> I get that, but I still don't understand why you would forcefully need
> it to be a variable still then if you know the value is gonna be
> constant, of course besides global visibility or in iterations

because constants are expensive in PHP when "define()" is a function 
call and "const" is very limited for no good reason

"no good reason" because if it really would be compile time the 
following won't work and so why can't you use 'const' within a 
if-statement when you in fact can CONCAT two with `define()` set constant 
which are part of a if-statement themself
____________________________________________________

if(PHP_SAPI !== 'cli')
{
  define('MY_PHP_SELF', $_SERVER['SCRIPT_NAME']);
  define('rh_serverurl', PROTOCOL_PREFIX . MY_SERVER_NAME . $rh_port);
}
else
{
  define('MY_PHP_SELF', '/' . basename($_SERVER['SCRIPT_NAME']));
  define('rh_serverurl', 'http://localhost');
}
const rh_phpself = rh_serverurl . MY_PHP_SELF;

---

## #99673 — Marco Pivetta — 2017-06-29T09:08:39+00:00

URL: https://externals.io/message/99657#99673 · In reply to: #99672

Final is about having immutable data. Immutable doesn't mean that it's a
system wide constant, it means that it's referentially pure in its scope.



>
>
> Am 29.06.2017 um 04:50 schrieb Kalle Sommer Nielsen:
>
> > […]
>
> because constants are expensive in PHP when "define()" is a function call
> and "const" is very limited for no good reason
>
> "no good reason" because if it really would be compile time the following
> won't work and so why can't you use 'const' within a if-statement when you
> in fact can CONCAT two with `define()` set constant which are part of a
> if-statement themself
> ____________________________________________________
>
> if(PHP_SAPI !== 'cli')
> {
>  define('MY_PHP_SELF', $_SERVER['SCRIPT_NAME']);
>  define('rh_serverurl', PROTOCOL_PREFIX . MY_SERVER_NAME . $rh_port);
> }
> else
> {
>  define('MY_PHP_SELF', '/' . basename($_SERVER['SCRIPT_NAME']));
>  define('rh_serverurl', 'http://localhost');
> }
> const rh_phpself = rh_serverurl . MY_PHP_SELF;

---

## #99674 — lists@rhsoft.net — 2017-06-29T09:19:07+00:00

URL: https://externals.io/message/99657#99674 · In reply to: #99673

Am 29.06.2017 um 11:08 schrieb Marco Pivetta:
> Final is about having immutable data. Immutable doesn't mean that it's a 
> system wide constant, it means that it's referentially pure in its scope.

i refered to "why you would forcefully need it to be a variable still 
then if you know the value is gonna be constant" and as long constants 
in PHP are a) very expensive and b) "const" pretends to be compile time 
which is provable wrong with my sample code are terrible to use

in other languages like Visual Basic constants are fast, in PHP they are 
slow, both in define and access

> On 29 Jun 2017 11:05 AM, "lists@rhsoft.net <mailto:lists@rhsoft.net>" 
> <lists@rhsoft.net <mailto:lists@rhsoft.net>> wrote:
> 
> 
> 
>     Am 29.06.2017 um 04:50 schrieb Kalle Sommer Nielsen:
> 
>         2017-06-28 20:46 GMT+02:00 David Rodrigues
>         <david.proweb@gmail.com <mailto:david.proweb@gmail.com>>:
> 
>             The "final" keyworks make a "local scope" variable value
>             "blocked to
>             rewrite" after instantiate it.
>             Okay, it sounds like a "const", and it is, but "not as we
>             known it".
> 
> 
>         I get that, but I still don't understand why you would
>         forcefully need
>         it to be a variable still then if you know the value is gonna be
>         constant, of course besides global visibility or in iterations
> 
> 
>     because constants are expensive in PHP when "define()" is a function
>     call and "const" is very limited for no good reason
> 
>     "no good reason" because if it really would be compile time the
>     following won't work and so why can't you use 'const' within a
>     if-statement when you in fact can CONCAT two with `define()` set
>     constant which are part of a if-statement themself
>     ____________________________________________________
> 
>     if(PHP_SAPI !== 'cli')
>     {
>       define('MY_PHP_SELF', $_SERVER['SCRIPT_NAME']);
>       define('rh_serverurl', PROTOCOL_PREFIX . MY_SERVER_NAME . $rh_port);
>     }
>     else
>     {
>       define('MY_PHP_SELF', '/' . basename($_SERVER['SCRIPT_NAME']));
>       define('rh_serverurl', 'http://localhost');
>     }
>     const rh_phpself = rh_serverurl . MY_PHP_SELF;

---

## #99675 — Marco Pivetta — 2017-06-29T09:25:32+00:00

URL: https://externals.io/message/99657#99675 · In reply to: #99674

> in other languages like Visual Basic constants are fast, in PHP they are
> slow, both in define and access
>

Two things here:

 1. don't ever consider visual basic for any comparison of any sort: it's
basically (ha!) the worst example of a programming language that I can
think of before malborge
 2. speed is not relevant in this scope: program correctness is. Final
properties would allow switching value object representations from accessor
(getter) based logic (extremely slow) to public property based (less
overhead, also in writing).

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

---

## #99676 — lists@rhsoft.net — 2017-06-29T09:33:36+00:00

URL: https://externals.io/message/99657#99676 · In reply to: #99675

Am 29.06.2017 um 11:25 schrieb Marco Pivetta:
> On Thu, Jun 29, 2017 at 11:19 AM, lists@rhsoft.net 
> <mailto:lists@rhsoft.net> <lists@rhsoft.net <mailto:lists@rhsoft.net>> 
> wrote:
> 
>     in other languages like Visual Basic constants are fast, in PHP they
>     are slow, both in define and access
> 
> 
> Two things here:
> 
>   1. don't ever consider visual basic for any comparison of any sort: 
> it's basically (ha!) the worst example of a programming language that I 
> can think of before malborge

stop it - many people say the same about PHP

>   2. speed is not relevant in this scope: program correctness is. Final 
> properties would allow switching value object representations from 
> accessor (getter) based logic (extremely slow) to public property based 
> (less overhead, also in writing)

in which scope is speed not relevant?

depends on your application, in my scopes i try to avoid expensive 
opcodes and useless function calls, program correctness is a completly 
different thing and it's not one or the other but both

---

## #99677 — David Rodrigues — 2017-06-29T09:58:50+00:00

URL: https://externals.io/message/99657#99677 · In reply to: #99675

I will try answer the questions:

> I get that, but I still don't understand why you would forcefully need
> it to be a variable still then if you know the value is gonna be
> constant, of course besides global visibility or in iterations

"final" is not "const". "final" mean a initial state that will never be
modified, but it could be initialized with different values on same
runtime. It is like I say "my name is David and will be all the time David
when I am on an informal context" and "my name is Rodrigues and will be all
the time Rodrigues when I am on a forma context", on same "document".
https://pastebin.com/QCrmrZQe

> True we could re-use the final keyword, but think about it this way,
> we got final methods and final classes which means it cannot be
> overridden/extended respectively, if the final keyword then would also
> apply to variables but it would mean they could not be written to,
> that would create a WTF-factor.

It is done on Java, for instance. We can use "final" on classes or
functions that mean that it cannot be overrided, or "final" in variables,
that mean that it cannot be re-referenced (rewrite after initialization).
And not seems strange to me. We could "abstract the term" to understand
that in any of cases (for classes, function or variables) the information
could not be overrided after defined.

> The readonly keyword would work for any visibility modifiers, so
> inherited classes or extending classes may read a protected property,
> but not modify it as well:

For me, the readonly keyword should be implemented on future to another
case: make a public property writeable only by the own class. But it is for
another discussion.

> The `final` modifier would likely clash with property type definitions,
if those ever make it to the language.
> Still, a few pain-points remain:
>  * References to properties (you cannot reference final properties
anymore, and that is effectively a BC break for anything using reflection
and closure scope binding)

I don't know if I understand, but for properties you could redefine a final
property on constructor (as Java). https://pastebin.com/bTZcUT33

>  * Arrays and resources as properties

You can modify arrays or resources on final variables, since that you don't
modify the reference. https://pastebin.com/D38wL8x7

>  * Named (Factory) constructors

I don't understand.

>  * Property nullability - how do you define if a property was written to
the "last valid time" before freezing it

Because PHP don't have support to "variable initialization" (eg. "$name;")
then you should only initializate it when you will write the initial (and
freezed) value. https://pastebin.com/Ua6DFUC1

 > * Unset properties and providing an alternative mechanism to distinguish
"uninitiated",  "undefined" and "frozen" in he event of final properties
usage, without breaking current property access semantics

It will be modified. Final variables still are a variable, but with the
status that "never change after initializate" (a flag). We can just
implement a new reflection method to properties to identify if it
isFinal(), or even for variables like "is_final($var)". By other side, this
last doesn't make sense because the final variable is just a "code
documentation" to the own dev knows that is not allowed modify it anymore.
Maybe we need implements that only for ReflectionProperty (first case),
because it could be part of a code that the user have not modify access
(eg. vendor code). https://pastebin.com/jSjNQACd




2017-06-29 6:25 GMT-03:00 Marco Pivetta <ocramius@gmail.com>:

> On Thu, Jun 29, 2017 at 11:19 AM, lists@rhsoft.net <lists@rhsoft.net>
> wrote:
>
> > […]
>
> Two things here:
>
>  1. don't ever consider visual basic for any comparison of any sort: it's
> basically (ha!) the worst example of a programming language that I can
> think of before malborge
>  2. speed is not relevant in this scope: program correctness is. Final
> properties would allow switching value object representations from accessor
> (getter) based logic (extremely slow) to public property based (less
> overhead, also in writing).
>
> Marco Pivetta
>
> http://twitter.com/Ocramius
>
> http://ocramius.github.com/
>



-- 
David Rodrigues

---

## #99678 — Dan Ackroyd — 2017-06-29T10:07:15+00:00

URL: https://externals.io/message/99657#99678 · In reply to: #99670

> References to properties ...is effectively a BC break for anything
> using reflection and closure scope binding

No it's not.

If that feature was brought into PHP, any code that is currently
valid, that the library is capable of reflecting, would still be valid
code, that the library would still be capable of reflecting.

Yes, there would be some new syntax which the library wouldn't be
aware of, which wouldn't be supported in the library, but that is not
a BC break.

Adding new syntax to a language does mean that people who have
libraries that inspect code based on the current syntax would need to
choose between:

* Updating the library to support the new syntax, or asking for a PR for that.

* Saying that the library can inspect code up to the version before
the new syntax was introduced, but doesn't support later code.

I can see that would be annoying for the authors of those libraries,
as they would obviously prefer to not have to make that choice, but it
isn't a BC break.


> *snip - lots of difficult to solve technical problems*
>
> This is the exact same set of problems we had with the typed properties
> RFC, and which caused the RFC to fail: please take all these in
> consideration while designing the feature.

Yup. I think any discussion without at least some kind of plan for
dealing with the technical problems for implementing this isn't likely
to be productive.

cheers
Dan

---

## #99679 — Marco Pivetta — 2017-06-29T10:14:17+00:00

URL: https://externals.io/message/99657#99679 · In reply to: #99677

Hi David,

On Thu, Jun 29, 2017 at 11:58 AM, David Rodrigues <david.proweb@gmail.com>
wrote:

> > […]
> if those ever make it to the language.
> > […]
> anymore, and that is effectively a BC break for anything using reflection
> and closure scope binding)
>
> I don't know if I understand, but for properties you could redefine a
> final property on constructor (as Java). https://pastebin.com/bTZcUT33
>

No, the problem is following:

class Foo { final public $bar = 'baz'; }

$foo = new Foo;

$bar = & $foo->bar;

$bar = 'taz';

var_dump($foo->bar);

This kind of ugly code will break.


>  * Arrays and resources as properties
>
> You can modify arrays or resources on final variables, since that you
> don't modify the reference. https://pastebin.com/D38wL8x7
>

That doesn't make it "final", although I get your point, and yes, it
basically prevents decreasing the reference count on that particular
property. I think this kills the usefulness of the feature, but it's indeed
still useful.


> > […]
>
> I don't understand.
>

Relatively common pattern:

class Foo {
    private final $bar;
    private function __construct() { /* hammertime */ }
    public static function create($something) : self {
        $instance = new self();
        $instance->bar = $something;
        return $instance;
    }
}

See also http://verraes.net/2014/06/named-constructors-in-php/


> > […]
> the "last valid time" before freezing it
>
> Because PHP don't have support to "variable initialization" (eg. "$name;")
> then you should only initializate it when you will write the initial (and
> freezed) value. https://pastebin.com/Ua6DFUC1
>

Got it, so a "first write" would be equivalent to a freeze operation? When
do you seal the property if the value isn't overwritten? Would you disable
default values for properties that are declared `final`?


>
> > […]
> distinguish "uninitiated",  "undefined" and "frozen" in he event of final
> properties usage, without breaking current property access semantics
>
> It will be modified. Final variables still are a variable, but with the
> status that "never change after initializate" (a flag). We can just
> implement a new reflection method to properties to identify if it
> isFinal(), or even for variables like "is_final($var)". By other side, this
> last doesn't make sense because the final variable is just a "code
> documentation" to the own dev knows that is not allowed modify it anymore.
> Maybe we need implements that only for ReflectionProperty (first case),
> because it could be part of a code that the user have not modify access
> (eg. vendor code). https://pastebin.com/jSjNQACd
>

The reflection API is a given, but the problem is still the same:

class Foo {
    private final $foo;
    private $lazyLoad;
    public function saySomething() {
        return 'Saying ' . $this->foo;
    }
    private function __construct() {
    }
    public static function new() : self {
        $instance = new self();
        $instance->foo = 'something';
        return $instance;
    }
    public static function newLazy() : self {
        $instance = new self();
        $instance->lazyLoad = function () use ($instance) {
            $instance->foo = 'something lazy';
        };
        unset($instance->foo);
        return $instance;
    }
    public function __get($name) {
        ($this->lazyLoad)();
        return $this->foo;
    }
}

$foo = Foo::new();
var_dump($foo->saySomething());
$lazyFoo = Foo::newLazy();
var_dump($lazyFoo->saySomething());

https://3v4l.org/UPVWF

Hope that clarifies it.


Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

---

## #99680 — Marco Pivetta — 2017-06-29T10:16:37+00:00

URL: https://externals.io/message/99657#99680 · In reply to: #99678

Hey Dan,

On Thu, Jun 29, 2017 at 12:07 PM, Dan Ackroyd <danack@basereality.com>
wrote:

> 
>
> > […]
>
> No it's not.
>
> If that feature was brought into PHP, any code that is currently
> valid, that the library is capable of reflecting, would still be valid
> code, that the library would still be capable of reflecting.
>

We discussed this before: any library designed around the capability of
dealing with a generic object would break in these scenarios, which is why
I always bring it up. It needs to be considered in an RFC, including
possible mitigation and alternatives.

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/
