ID:               49328
 User updated by:  rayro at gmx dot de
 Reported By:      rayro at gmx dot de
 Status:           Bogus
 Bug Type:         Class/Object related
 Operating System: Windows XP
 PHP Version:      5.3.0
 New Comment:

Ok for now, this is more a feature request than a bug i think... ^^
Just gimme a try to explain it, thanks :)

i talk about how class abstraction can be extended with such nice
features like the __call->private issue described in this submission.

My idea was that every method/property defined not abstracted in an
abstract class should be a template/pattern for the extended class,
giving the full control to redefine it but acting like a default without
loosing the context in the extended class.

With this change it would be possible to define private methods in
abstract classes that are redefineable, except for methods defined as
final.
All magic methods defined in the abstract class should only run in
context of the extended class, since it does never make sense for me
that they got context of the abstract class. With this change it will be
possible to e.g. create magic methods or normal methods that "act like
defined" in the extended class.

to 3) on one side, it is a nice feature to build a object tree having
control to the higher static properties from the class, on the other
side it will create negative side effects if setting this variable in
the extended class. I think that this behaviour should be removed, since
it makes much more sense to talk to the parent::$static, not to the
self::$static... Here too, it makes sense to allow the abstract
definition of statics, so the owner is requestet to redefine the
variable. Same for class constant like self::VERSION, that should be
redefined in the extended class...
Look at this example that uses references, where the static reference
is lost, as it should work in abstraction. It is much like the last
example, except the reference to a global variable here:

Reproduce code:
---------------
abstract class Foo {
        static public $test;
}
class Bar extends Foo {

}
$my_variable = 'test';
Foo::$test =& $my_variable;
var_dump(Foo::$test);
var_dump(Bar::$test);
Bar::$test = 'baz';
var_dump(Foo::$test);
var_dump(Bar::$test);

Expected result:
----------------
string(4) "test"
string(4) "test"
string(3) "baz"
string(3) "baz"

Actual result:
--------------
string(4) "test"
NULL
string(4) "test"
string(3) "baz"


Previous Comments:
------------------------------------------------------------------------

[2009-08-22 22:51:31] col...@php.net

Well, with your last example you're pointing to a totally different
problem composed of 3 PHP facts:

1) you cannot dynamically define static properties
2) static properties are strictly bound to the class in which they are
defined
3) Access to undefined static properties fallback to their parent
class.

IMO, (3) is highly arguable, but it has nothing to do with the problem
at hand.

------------------------------------------------------------------------

[2009-08-22 20:57:44] rayro at gmx dot de

Spending time sorting my brain, i agree with the conclusion that the
context is not the same while extending a _class_, and i have to use
protected methods here, but this is an _abstract class_?
It is not really intelligible for me that abstract classes gaining a
context while their not instantiable, nor i'm convinced of the
abstraction design over all. :/
In my opinion, the context of the abstracted class should "fully"
relate to the context of the extending class. Furthermore statically
definitions should render in the class scope/context, and none static
calls should result in an error if called on abstracted class (as it is
with class vars).
The definition of (not abstracted) functions in a abstract class should
ever run in the context of the extended class, so theres no lsb
necessary (e.g. __CLASS__ resolves to the classname of the extended
class).
Surely a topic to talk about?

The following abstract class predefines the static property and method,
but the result should vary towards a normal class definition.

Reproduce code:
---------------
abstract class Foo {
        public static $text;
        public static function test() {
                var_dump('get_called_class(): '.get_called_class());
                var_dump(static::$text);
        }
}
class Bar extends Foo { }
Foo::$text = '1';
Foo::test();
Bar::test();
Bar::$text = '2';
Foo::test();
Bar::test();

Expected result:
----------------
string(23) "get_called_class(): Foo"
string(1) "1"
string(23) "get_called_class(): Bar"
NULL
string(23) "get_called_class(): Foo"
string(1) "1"
string(23) "get_called_class(): Bar"
string(1) "2"

Actual result:
--------------
string(23) "get_called_class(): Foo"
string(1) "1"
string(23) "get_called_class(): Bar"
string(1) "1"
string(23) "get_called_class(): Foo"
string(1) "2"
string(23) "get_called_class(): Bar"
string(1) "2"

------------------------------------------------------------------------

[2009-08-22 15:00:27] col...@php.net

There 2 different things here

1) conditions required to call __call
2) requirements to call private methods

So:
1) in 5.3, calling private methods from invalid context will trigger
__call if available.

2) You can only call private methods of the class defining the function
you're in.

in this case, __call is defined in Foo, so it cannot call private
methods that are not defined in Foo. Since it cannot call it, it will
trigger __call again, causing the loop.

------------------------------------------------------------------------

[2009-08-22 13:47:52] rayro at gmx dot de

Addition:
The following __call function will also generate an endless loop, and
there will be _no output_ if you uncomment Foo::test() here:

abstract class Foo {
        function __call($f, $a) {
                return $this->{$f}($a[0]);
        }
//      private function test() { }
}

class Bar extends Foo {
        private function test($a) {
                var_dump($a);
        }
}
$bar = new Bar();
$bar->test('hello');

------------------------------------------------------------------------

[2009-08-22 13:34:13] rayro at gmx dot de

Well, does Foo::__call has access to Bar::test() if the private
function is defined in the abstract class?
Although, since 5.3 __call can handle private functions (place __call
in Bar), this _should_ be argumented as a bug i think?
The access level should not matter while extending?

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/49328

-- 
Edit this bug report at http://bugs.php.net/?id=49328&edit=1

Reply via email to