RFC: https://wiki.php.net/rfc/locale_independent_float_to_string
. Removed support for deprecated curly braces for offset access
RFC: https://wiki.php.net/rfc/deprecate_curly_braces_array_access
+ . Applying the final modifier on a private method will now produce a warning
+ unless that method is the constructor.
+ RFC: https://wiki.php.net/rfc/inheritance_private_methods
- COM:
. Removed the ability to import case-insensitive constants from type
RFC: https://wiki.php.net/rfc/constructor_promotion
. Added support for `match` expression.
RFC: https://wiki.php.net/rfc/match_expression_v2
+ . Private methods declared on a parent class no longer enforce any
+ inheritance rules on the methods of a child class. (with the exception of
+ final private constructors)
+ RFC: https://wiki.php.net/rfc/inheritance_private_methods
- Date:
. Added DateTime::createFromInterface() and
(new C)->test();
class D {
- private final function method(&$x) {
+ private function method(&$x) {
++$x;
}
}
zend_string *lcname;
+ if ((fn_flags & ZEND_ACC_PRIVATE) && (fn_flags & ZEND_ACC_FINAL) && !zend_is_constructor(name)) {
+ zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
+ }
+
if (in_interface) {
if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) {
zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
uint32_t parent_flags = parent->common.fn_flags;
zend_function *proto;
+ if (UNEXPECTED((parent_flags & ZEND_ACC_PRIVATE) && !(parent_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_CTOR))) {
+ if (!check_only) {
+ child->common.fn_flags |= ZEND_ACC_CHANGED;
+ }
+ /* The parent method is private and not an abstract so we don't need to check any inheritance rules */
+ return INHERITANCE_SUCCESS;
+ }
+
if (!checked && UNEXPECTED(parent_flags & ZEND_ACC_FINAL)) {
if (check_only) {
return INHERITANCE_ERROR;
child->common.fn_flags |= ZEND_ACC_CHANGED;
}
- if ((parent_flags & ZEND_ACC_PRIVATE) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
- return INHERITANCE_SUCCESS;
- }
-
proto = parent->common.prototype ?
parent->common.prototype : parent;
public $a = 'base';
// disallow cloning once forever
- final private function __clone() {}
+ final protected function __clone() {}
}
class test extends base {
--- /dev/null
+--TEST--
+Final private constructors cannot be overridden
+--FILE--
+<?php
+
+class Base
+{
+ private final function __construct()
+ {
+ }
+}
+class Extended extends Base
+{
+ public function __construct()
+ {
+ }
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot override final method Base::__construct() in %s on line %d
--- /dev/null
+--TEST--
+Ensure private methods with the same name are not checked for inheritance rules - final
+--FILE--
+<?php
+class A {
+ function callYourPrivates() {
+ $this->normalPrivate();
+ $this->finalPrivate();
+ }
+ function notOverridden_callYourPrivates() {
+ $this->normalPrivate();
+ $this->finalPrivate();
+ }
+ private function normalPrivate() {
+ echo __METHOD__ . PHP_EOL;
+ }
+ final private function finalPrivate() {
+ echo __METHOD__ . PHP_EOL;
+ }
+}
+class B extends A {
+ function callYourPrivates() {
+ $this->normalPrivate();
+ $this->finalPrivate();
+ }
+ private function normalPrivate() {
+ echo __METHOD__ . PHP_EOL;
+ }
+ final private function finalPrivate() {
+ echo __METHOD__ . PHP_EOL;
+ }
+}
+$a = new A();
+$a->callYourPrivates();
+$a->notOverridden_callYourPrivates();
+$b = new B();
+$b->callYourPrivates();
+$b->notOverridden_callYourPrivates();
+?>
+--EXPECTF--
+Warning: Private methods cannot be final as they are never overridden by other classes %s
+
+Warning: Private methods cannot be final as they are never overridden by other classes %s
+A::normalPrivate
+A::finalPrivate
+A::normalPrivate
+A::finalPrivate
+B::normalPrivate
+B::finalPrivate
+A::normalPrivate
+A::finalPrivate
--- /dev/null
+--TEST--
+Ensure private methods with the same name are not checked for inheritance rules - static
+--FILE--
+<?php
+class A {
+ static private function foo() { }
+ private function bar() {}
+}
+class B extends A {
+ private function foo() {}
+ static private function bar() {}
+}
+echo 'OK';
+?>
+--EXPECT--
+OK
--- /dev/null
+--TEST--
+Ensure private methods with the same name are not checked for inheritance rules - abstract
+--FILE--
+<?php
+class A {
+ private function test() {}
+}
+abstract class B extends A {
+ abstract function test();
+}
+echo 'OK';
+?>
+--EXPECT--
+OK