rfc:locked-classes

This is an old revision of the document!


PHP RFC: Locked Classes

Introduction

Object properties in PHP are primarily defined in class definitions; however, they can also be added to or removed from individual instances at any time. This RFC proposes an opt-in method for a class definition to disable this behaviour for all instances of that class.

While setting properties which were not declared in a class definition, or unsetting properties which were declared, can be a useful tool, like many of PHP's dynamic features, it also makes certain mistakes easier. For instance, if a class defines a property public $normalise=true;, and a user writes $instance->normalize=false;, a new property will be silently added. Static analysis can highlight this mistake, but the language itself issues no warning.

Changing this behaviour for all objects would be a significant change to the language, with the potential to break a large amount of existing code. However, code written with no intention of using this dynamic behaviour would benefit from a way to switch it off.

Proposal

A “locked” class is any class whose definition includes the modifier keyword “locked”, regardless of any other modifiers. An instance of a locked class behaves like any other object, except that:

  • Attempting to set a property on the instance which was not declared in the class (or inherited from one of its parent classes) will throw an error, and the instance will not be modified.
  • Attempting to read a property on the instance which was not declared (or inherited) will throw an error, rather than raising a Notice and evaluating to null.
  • Attempting to call unset() on any property of the instance will throw an error, and the instance will not be modified.

This behaviour will interact with the existing magic methods as follows:

  • If the class declares a magic _\_set method, this will still be called when attempting to set an undefined property instead of the error being thrown.
  • If the class declares a magic _\_get method, this will still be called when attempting to read an undefined property instead of the error being thrown.
  • If the class declares a magic _\_unset method, this will be called when attempting to unset any property which is not declared in the class, or is declared private. For properties which are declared and public, this magic method is not called; if the class is declared “locked”, this case will therefore throw an error.

Naming

Newer versions of ECMAScript / JavaScript have similar functionality, under the name "sealed objects". However, the term “sealed class” has an unrelated meaning in languages such as Kotlin and C#, to do with limiting the class's participation in inheritance.

Since the proposed modifier applies to a class, not an instance, it would be confusing to use the keyword “sealed” in this sense, so the synonym “locked” has been chosen instead.

Backward Incompatible Changes

No internal classes, or classes in unmodified code, will change behaviour.

Since it is a new keyword, it will not be possible to “polyfill” this functionality, or declare a “locked class” in code which needs to be compatible with earlier PHP versions.

Proposed PHP Version(s)

Next PHP 7.x

RFC Impact

To Opcache

To be determined: are there any optimisations which interact with the behaviours being changed?

To Reflection

* ReflectionClass::IS_LOCKED constant * Changes to ReflectionClass::getModifiers() and Reflection::getModifierNames() * ReflectionClass::isLocked() method

Unaffected PHP Functionality

List existing areas/features of PHP that will not be changed by the RFC.

This helps avoid any ambiguity, shows that you have thought deeply about the RFC's impact, and helps reduces mail list noise.

Future Scope

TODO

Proposed Voting Choices

Should “locked classes” as described above be added to PHP 7.x? A 2/3 majority is required.

Patches and Tests

Implementation

TODO: After the project is implemented, this section should contain

  1. the version(s) it was merged into
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature
  4. a link to the language specification section (if any)

References

TODO

Rejected Features

None yet

rfc/locked-classes.1552228458.txt.gz · Last modified: 2019/03/10 14:34 by imsop