# Class Posing

- Thread: https://externals.io/message/32538
- Original archive: https://news-web.php.net/php.internals/32538
- Started by Sebastian Bergmann on 2007-10-02T09:32:53+00:00
- Messages: 17
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #32538 — Sebastian Bergmann — 2007-10-02T09:32:53+00:00

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

From [1]:

   Objective-C permits a class to wholly replace another class within a
   program. The replacing class is said to "pose as" the target class.
   All messages sent to the target class are then instead received by
   the posing class.

   There are several restrictions on which classes can pose:

     * A class may only pose as one of its direct or indirect
       superclasses.

     [The other restrictions do not apply to PHP]

 Earlier this year, Johannes implemented class posing for PHP as follows:

   <?php
   class Foo {}
   class Bar extends Foo {}

   function new_overload($className)
   {
       if ($className == 'Foo') {
           return new Bar;
       }

       // ...
   }

   $o = new Foo;
   // $o is an object of Foo.

   register_new_overload('new_overload');

   $o = new Foo;
   // $o is an object of Bar.
   ?>

 We (Johannes, Marcus, Sara, and myself) then discussed where to put this
 functionality. Outside of core, there were two places that both make
 sense: pecl/operator and pecl/runkit.

 However, to make this a viable mechanism that can be used in tools such
 as PHPUnit (for which I could really use this functionality), we agreed
 that it actually belongs into the core.

 Opinions? Needless to say that I would love to see this in PHP 5.3 ;-)

 --
 [1] http://en.wikipedia.org/wiki/Objective_C#Posing

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #32543 — dz@bitxtender.com — 2007-10-02T13:02:29+00:00

URL: https://externals.io/message/32538#32543 · In reply to: #32538

would it be possible to overload final classes?

- David


Am 02.10.2007 um 11:32 schrieb Sebastian Bergmann:

>  From [1]:
>
>    Objective-C permits a class to wholly replace another class  
> within a
>    program. The replacing class is said to "pose as" the target class.
>    All messages sent to the target class are then instead received by
>    the posing class.
>
>    There are several restrictions on which classes can pose:
>
>      * A class may only pose as one of its direct or indirect
>        superclasses.
>
>      [The other restrictions do not apply to PHP]
>
>  Earlier this year, Johannes implemented class posing for PHP as  
> follows:
>
>    <?php
>    class Foo {}
>    class Bar extends Foo {}
>
>    function new_overload($className)
>    {
>        if ($className == 'Foo') {
>            return new Bar;
>        }
>
>        // ...
>    }
>
>    $o = new Foo;
>    // $o is an object of Foo.
>
>    register_new_overload('new_overload');
>
>    $o = new Foo;
>    // $o is an object of Bar.
>    ?>
>
>  We (Johannes, Marcus, Sara, and myself) then discussed where to  
> put this
>  functionality. Outside of core, there were two places that both make
>  sense: pecl/operator and pecl/runkit.
>
>  However, to make this a viable mechanism that can be used in tools  
> such
>  as PHPUnit (for which I could really use this functionality), we  
> agreed
>  that it actually belongs into the core.
>
>  Opinions? Needless to say that I would love to see this in PHP  
> 5.3 ;-)
>
>  --
>  [1] http://en.wikipedia.org/wiki/Objective_C#Posing
>
> -- 
> Sebastian Bergmann                          http://sebastian- 
> bergmann.de/
> GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514  
> B85B 5D69

---

## #32544 — Guilherme Blanco — 2007-10-02T13:15:24+00:00

URL: https://externals.io/message/32538#32544 · In reply to: #32538

Hi Sebastian and PHP list,


That's a very interesting idea and I'd use it too. Yesterday night I
was developing a set of classes that it could apply this idea too.


Altho I found this idea really interesting, I have a suggestion for
it. Instead of use a function to handle new overloads, I suggest a
magic method, something like __new.

The idea behind this:
<?php

class Foo {
    function __construct($type = 'Foo') { echo 'Created ', $type; }
    function __new( $type ) {
        if ($type == 'Bar') {
            return new Bar();
        }
    }
}

class Bar {
    function __construct() { echo 'Bar here!'; }
}

$bar = new Foo('Bar'); // Creates Bar instance

?>


Dunno the impact of this in the source, but my humble idea is that it
independs of inheritance. Of course this would be more acceptable for
super and extended classes, and here is a true usage of it:


class Validator {
    private $_country;

    function __construct() {}

    function __new($country) {
        switch ($country) {
        case 'Brazil': return new Validator_Brazil();
        default: return new Validator_US();
        }
    }
}

interface IValidator_Country  {
    function validate($type, $value);
}

class Validator_Brazil implements IValidator_Country {
    function __construct() { ... }
    function validate($type, $value) { ... }
}

class Validator_US implements IValidator_Country {
    function __construct() { ... }
    function validate($type, $value) { ... }
}

$o = new Validator('Brazil'); // Creates Validator_Brazil

echo ($o->validate('zip', '13561000')) ? 'Zip code is valid' : 'Zip is
not valid';



The basic idea is to check for __new existance and call it instead of
__construct. If there's no return or null after __new call, then call
the __contruct as currently it does.


So, what do you think??? =)



Regards,



>  From [1]:
>
>    Objective-C permits a class to wholly replace another class within a
>    program. The replacing class is said to "pose as" the target class.
>    All messages sent to the target class are then instead received by
>    the posing class.
>
>    There are several restrictions on which classes can pose:
>
>      * A class may only pose as one of its direct or indirect
>        superclasses.
>
>      [The other restrictions do not apply to PHP]
>
>  Earlier this year, Johannes implemented class posing for PHP as follows:
>
>    <?php
>    class Foo {}
>    class Bar extends Foo {}
>
>    function new_overload($className)
>    {
>        if ($className == 'Foo') {
>            return new Bar;
>        }
>
>        // ...
>    }
>
>    $o = new Foo;
>    // $o is an object of Foo.
>
>    register_new_overload('new_overload');
>
>    $o = new Foo;
>    // $o is an object of Bar.
>    ?>
>
>  We (Johannes, Marcus, Sara, and myself) then discussed where to put this
>  functionality. Outside of core, there were two places that both make
>  sense: pecl/operator and pecl/runkit.
>
>  However, to make this a viable mechanism that can be used in tools such
>  as PHPUnit (for which I could really use this functionality), we agreed
>  that it actually belongs into the core.
>
>  Opinions? Needless to say that I would love to see this in PHP 5.3 ;-)
>
>  --
>  [1] http://en.wikipedia.org/wiki/Objective_C#Posing
>
> --
> Sebastian Bergmann                          http://sebastian-bergmann.de/
> GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69
>
> --
> 
> 
>
>


-- 
Guilherme Blanco - Web Developer
CBC - Certified Bindows Consultant
Cell Phone: +55 (16) 9166-6902
MSN: guilhermeblanco@hotmail.com
URL: http://blog.bisna.com
São Carlos - SP/Brazil

---

## #32545 — Richard Quadling — 2007-10-02T13:37:48+00:00

URL: https://externals.io/message/32538#32545 · In reply to: #32543

> would it be possible to overload final classes?
>
> - David
>
>
> Am 02.10.2007 um 11:32 schrieb Sebastian Bergmann:
>
> > […]

You're code looks like a factory. Is that your intention? Maybe
__factory would be a more obvious name?



-- 
-----
Richard Quadling
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
"Standing on the shoulders of some very clever giants!"

---

## #32548 — Sebastian Bergmann — 2007-10-02T13:54:52+00:00

URL: https://externals.io/message/32538#32548 · In reply to: #32544

Guilherme Blanco schrieb:
> Altho I found this idea really interesting, I have a suggestion for
> it. Instead of use a function to handle new overloads, I suggest a
> magic method, something like __new.

 __new() was what I initially proposed to Johannes but IIRC there were
 some performance implications with that. Johannes?

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #32549 — Sebastian Bergmann — 2007-10-02T13:56:13+00:00

URL: https://externals.io/message/32538#32549 · In reply to: #32545

Richard Quadling schrieb:
> You're code looks like a factory. Is that your intention? Maybe
> __factory would be a more obvious name?

 The application of this mechanism is not limited to implementing
 factories and singletons.

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #32552 — Jared Williams — 2007-10-02T14:33:36+00:00

URL: https://externals.io/message/32538#32552 · In reply to: #32538

Ideally think I'd prefer it finer grained... 

interface A
{
}

class AImpl implements A
{
}

	register('A', function() { return new AImpl(); });
	register('Foo', function() { return new Bar(); });
	
	$foo = new Foo();	
	$a = new A();

Would also require functions being values... Which would also be nice. 

J


> -----Original Message-----
> From: news [mailto:news@sea.gmane.org] On Behalf Of Sebastian Bergmann
> Sent: 02 October 2007 10:33
> To: internals@lists.php.net
> Subject: [PHP-DEV] Class Posing
> 
>  From [1]:
> 
>    Objective-C permits a class to wholly replace another 
> class within a
>    program. The replacing class is said to "pose as" the target class.
>    All messages sent to the target class are then instead received by
>    the posing class.
> 
>    There are several restrictions on which classes can pose:
> 
>      * A class may only pose as one of its direct or indirect
>        superclasses.
> 
>      [The other restrictions do not apply to PHP]
> 
>  Earlier this year, Johannes implemented class posing for PHP 
> as follows:
> 
>    <?php
>    class Foo {}
>    class Bar extends Foo {}
> 
>    function new_overload($className)
>    {
>        if ($className == 'Foo') {
>            return new Bar;
>        }
> 
>        // ...
>    }
> 
>    $o = new Foo;
>    // $o is an object of Foo.
> 
>    register_new_overload('new_overload');
> 
>    $o = new Foo;
>    // $o is an object of Bar.
>    ?>
> 
>  We (Johannes, Marcus, Sara, and myself) then discussed where 
> to put this  functionality. Outside of core, there were two 
> places that both make
>  sense: pecl/operator and pecl/runkit.
> 
>  However, to make this a viable mechanism that can be used in 
> tools such  as PHPUnit (for which I could really use this 
> functionality), we agreed  that it actually belongs into the core.
> 
>  Opinions? Needless to say that I would love to see this in 
> PHP 5.3 ;-)
> 
>  --
>  [1] http://en.wikipedia.org/wiki/Objective_C#Posing
> 
> -- 
> Sebastian Bergmann                          
> http://sebastian-bergmann.de/
> GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 
> C514 B85B 5D69
> 
> --
>  To 
> unsubscribe, visit: http://www.php.net/unsub.php

---

## #32558 — Stanislav Malyshev — 2007-10-02T16:53:16+00:00

URL: https://externals.io/message/32538#32558 · In reply to: #32538

>  Earlier this year, Johannes implemented class posing for PHP as follows:
> 
>    <?php
>    class Foo {}
>    class Bar extends Foo {}
> 
>    function new_overload($className)
>    {
>        if ($className == 'Foo') {
>            return new Bar;
>        }
> 
>        // ...
>    }
> 
>    $o = new Foo;
>    // $o is an object of Foo.
> 
>    register_new_overload('new_overload');
> 
>    $o = new Foo;
>    // $o is an object of Bar.
>    ?>

This looks like factory pattern. What's wrong with implementing it as 
factory?

>  However, to make this a viable mechanism that can be used in tools such
>  as PHPUnit (for which I could really use this functionality), we agreed
>  that it actually belongs into the core.

I personally don't see much of the use of it in the core, and it 
definitely adds very "magic" things - you don't know anymore what class 
you are instantiating when you run "new Foo". My opinion is it belongs 
to places like "runkit" which do tricks with the language, but I don't 
see much use for it in the core. Could you explain more why existing 
pattern won't work for the same?
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #32559 — Sebastian Bergmann — 2007-10-02T17:10:16+00:00

URL: https://externals.io/message/32538#32559 · In reply to: #32558

Stanislav Malyshev schrieb:
> This looks like factory pattern. What's wrong with implementing it as
> factory?

 Like I said before, the factory and singleton patterns are just example
 applications of this mechanism.

 What I want to use them for in PHPUnit is improving the Mock Objects
 system.

 Let us consider the following code:

   public function foo()
   {
       $bar    = new Bar;
       $returh = $bar->doSomething();

       // do something with $return

       return 'some value';
   }

 When I want to test the foo() method, I want to stub out the usage of
 the Bar class, for example, and have Bar::doSomething() return a
 pre-configured value instead of performing its normal operation.

 As I cannot pass a stubbed version of $bar into the method, I currently
 do not have a way to stub Bar.

 With class posing, however, I can override the "new Bar" and have it
 create an object of my stub implementation of Bar instead.

 I hope this makes my motivation for the feature more clear.

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #32562 — Stanislav Malyshev — 2007-10-02T17:29:27+00:00

URL: https://externals.io/message/32538#32562 · In reply to: #32559

>  Like I said before, the factory and singleton patterns are just example
>  applications of this mechanism.

Right, but I'd like to see why we *need* it - i.e. what it allows to do 
that other things don't. I'm afraid that we might have a case of 
featuritis here (not meaning this specific proposal, I'm talking more in 
general state of affairs) in 5.3 - we will turn PHP from simple language 
into minefield of magic methods where you can't possibly know what the 
code you are looking at actually does. It might be useful for some 
applications but might hurt the language as a whole. It also can have a 
lot of implications what have unintended - i.e. how typehints are 
supposed to work with this? How reflection and autoloading would work? 
What with static methods and variables?

>  What I want to use them for in PHPUnit is improving the Mock Objects
>  system.

As far as I know, Java has unit tests but doesn't allow replacing 
classes. How does it work in Java?

>  I hope this makes my motivation for the feature more clear.

Yes, I can see the motivation now, but I'm not entirely convinced 
allowing to replace classes with other classes would be the best 
solution. I know there are OO languages extensively using unit testing 
and not having this feature - I'd propose looking into how it is done there.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #32570 — Sebastian Bergmann — 2007-10-02T19:13:16+00:00

URL: https://externals.io/message/32538#32570 · In reply to: #32562

Stanislav Malyshev schrieb:
> As far as I know, Java has unit tests but doesn't allow replacing
> classes. How does it work in Java?

 Stubs / Mock Objects !== Unit Tests. Class Posing allows for better
 stubs / mock objects which in turn are tools to write better unit
 tests.

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #32571 — Stanislav Malyshev — 2007-10-02T20:20:36+00:00

URL: https://externals.io/message/32538#32571 · In reply to: #32570

>  Stubs / Mock Objects !== Unit Tests. Class Posing allows for better
>  stubs / mock objects which in turn are tools to write better unit
>  tests.

OK, I see that. The question is - does any of the known unit test 
systems use mock objects? Does it do that in the language that doesn't 
allow "new Foo" to create object of entirely unrelated class? If so - 
how it is usually done?
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #32584 — Sebastian Bergmann — 2007-10-03T05:29:07+00:00

URL: https://externals.io/message/32538#32584 · In reply to: #32562

Stanislav Malyshev schrieb:
> lot of implications what have unintended - i.e. how typehints are
> supposed to work with this? How reflection and autoloading would work?

 Typehints continue working because of the restriction that applies to
 this mechanism (see other mail(s)).

 Reflection{Class|Object}($object) does not care how $object has been
 created.

 __autoload() will be trigger just as before by the new operators inside
 the new-handler function (where they are, of course, not overloaded).

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #32591 — Sebastian Bergmann — 2007-10-03T14:33:45+00:00

URL: https://externals.io/message/32538#32591

Sebastian Bergmann schrieb:
> > […]
> Of course. We are not changing the class declaration (compile-time) but
> intercept the object creation (run-time).

 I may have been unclear here: a class may pose for a class that contains
 final methods. The posing class, by way of the restriction imposed on
 posing classes, can of course not override final methods of its parent
 class.

-- 
Sebastian Bergmann                          http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69

---

## #32615 — johannes@php.net — 2007-10-03T20:48:10+00:00

URL: https://externals.io/message/32538#32615 · In reply to: #32548

Hi,


> Guilherme Blanco schrieb:
> > […]
> 
>  __new() was what I initially proposed to Johannes but IIRC there were
>  some performance implications with that. Johannes?

The initial implementation Sebastian refers to is a conference hack I
did, which was done to see whether it's possible and give Sebastian a
thing to test the feature - there wasn't much thinking involved :-)

For an extension, which the current implementation is, using the
register function is the best approach I see. Else we would have to to
the look-up for the __new() function on every object instantiation. The
existence of that function can't be cached since it could be defined any
time. (While for an extension, used for testing, performance is not #1
prio)

If such an feature would become an engine feature one could cache the
declaration of __new() during the function declaration - which in that
case would, indeed, be the best.

But all that are implementation details. The question is: Do we need
such a feature inside Core PHP or is an extension overloading ZEND_NEW
enough?

The only need I see is mocking objects for a unit test. This is usually
done on a test system so installing such an extension shouldn't be to
hard (especially for somebody who is able to do unit tests using mock
objects...)

One might also think about taking XDebug's code coverage stuff and the
ZEND_NEW overloading and other stuff to build a phpunit extension - but
that's no topic for internals :-)

johannes

---

## #32620 — Stanislav Malyshev — 2007-10-03T21:51:01+00:00

URL: https://externals.io/message/32538#32620 · In reply to: #32615

> For an extension, which the current implementation is, using the
> register function is the best approach I see. Else we would have to to

I would prefer some special function to new handler. This feature has 
very narrow use (I still not entirely convinced it even belongs to core 
- it's too kludgy and can be easily worked around by using correct 
patterns).

> But all that are implementation details. The question is: Do we need
> such a feature inside Core PHP or is an extension overloading ZEND_NEW
> enough?

I'd say it's better to overload class' create_object and not an opcode. 
And I personally don't feel it's something that should be widely used, 
so Core may not be the best place. Maybe having some test extension 
(disabled by default, enabled on test machines) would be a better way?

-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #32629 — Timm Friebe — 2007-10-04T08:27:21+00:00

URL: https://externals.io/message/32538#32629 · In reply to: #32559

Hi,

>   public function foo()
>   {
>       $bar    = new Bar;
[...]
>   }
>
> When I want to test the foo() method, I want to stub out the usage of
> the Bar class, for example, and have Bar::doSomething() return a
> pre-configured value instead of performing its normal operation.

This is where you'd start refactoring the above sourcecode. I don't like 
this idea at all, because it really only helps you with testing legacy 
source you might not be able to or do not want to change (want to say: rare 
use-case IMO).

If you really need to intercept construction, you can still weave your 
interception functionality into sourcecode as you'd be doing in any AOP 
library. Simply write a stream wrapper for the file:// stream or add a 
filter to it to intercept all includes and / or requires your legacy code 
might contain and rewrite the sourcecode while loading, replacing "new Foo" 
by "newinstance('Foo')" - this might even be possible in a safe manner by 
using preg_replace.

- Timm
