Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.
We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.
These libraries, while greatly extensible, are also fairly self-extending.
That is, they include many classes that extend many classes, which is great.
As consumers of these libraries, we can extend the classes and consume the
API however we please, but there is one sticking point.
We cannot change classes that many other classes extend without extending or
changing each child class and then making sure that our code uses the new
class.
For a concrete example, I was working with the Zend_Form_Element subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want to
just start changing the Zend library files -
There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
-
Directly edit the Zend_Form_Element file in the library, -bad for updates
& other projects that use the library -
subclass Zend_Form_Element and change declaration of the descendants to
extend new class - same problems -
extend each child class and implement those subclasses in your app code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.
There could be a better way, if we could insert a class into the family
tree.
And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".
Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:
class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to change.
This way developers could "extend" default functionality and have existing
library classes pick up the new functionality without redeclaring anything
in the library.
Downstream classes would still override any methods that they redeclare. If
you wanted to have end-point classes in the library have different behavior,
you would overload them instead, such as
class My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.
Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added, without
me having to touch the library code.
I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind of
behavior... Prototypal languages perhaps, as is the case with javascript and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.
Thank you for your comments and thoughts!
Chris Trahey
Web Applications Developer
Database Administrator
CSISD [Technology]
footnote: I sent this message from a different address and it did not show
up. I tested sending to internals-help@lists.php.net and did not get a
response -so I assume there is an outgoing issue on my other server's side.
Forgive me if this message shows up again.
Hi,
Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.These libraries, while greatly extensible, are also fairly self-extending.
That is, they include many classes that extend many classes, which is great.As consumers of these libraries, we can extend the classes and consume the
API however we please, but there is one sticking point.We cannot change classes that many other classes extend without extending or
changing each child class and then making sure that our code uses the new
class.For a concrete example, I was working with the Zend_Form_Element subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want to
just start changing the Zend library files -There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
Directly edit the Zend_Form_Element file in the library, -bad for updates
& other projects that use the librarysubclass Zend_Form_Element and change declaration of the descendants to
extend new class - same problemsextend each child class and implement those subclasses in your app code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to change.
This way developers could "extend" default functionality and have existing
library classes pick up the new functionality without redeclaring anything
in the library.Downstream classes would still override any methods that they redeclare. If
you wanted to have end-point classes in the library have different behavior,
you would overload them instead, such asclass My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added, without
me having to touch the library code.I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind of
behavior... Prototypal languages perhaps, as is the case with javascript and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.
Even though it might look appealing from a framework user perspective,
it looks fishy from a language design perspective. It sounds like
you're trying to fix a framework design lack by a language trick.
For the fishy part: what happens to the old class? what about static
method calls on that old class? What if two classes overwrites the
same class? Basically it would mean there is no way to know at compile
time which class new Foo; is supposed to instantiate.
Thank you for your comments and thoughts!
Chris Trahey
Web Applications Developer
Database Administrator
CSISD [Technology]
footnote: I sent this message from a different address and it did not show
up. I tested sending to internals-help@lists.php.net and did not get a
response -so I assume there is an outgoing issue on my other server's side.
Forgive me if this message shows up again.
--
Etienne Kneuss
http://www.colder.ch
The old class is still there, think of it as if the inserted (overloading)
class extends the base (overloaded) class and any classes the were extending
the base now extend the inserted class. So as far as the runtime, it's
run-of-the-meill inheritance. Methods that are not re-implimented in the
inserted class are called in the original class, etc.
It could be implemented either at the time a class is loaded (when we see
'overloads' keyword) or perhaps in a function call:
overload_class('Library_Class', 'My_LibClass_Overload');
As for conflicts where multiple overloads are attempted, they could be in
sequence, such that you'd end up having an inheritance chain like this:
called_class <-- second_overload <-- first_overload <-- Library_Class <--
etc.
Hi,
On Sat, Mar 13, 2010 at 2:50 AM, Chris Trahey christrahey@gmail.com
wrote:Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.These libraries, while greatly extensible, are also fairly
self-extending.
That is, they include many classes that extend many classes, which is
great.As consumers of these libraries, we can extend the classes and consume
the
API however we please, but there is one sticking point.We cannot change classes that many other classes extend without extending
or
changing each child class and then making sure that our code uses the new
class.For a concrete example, I was working with the Zend_Form_Element
subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want
to
just start changing the Zend library files -There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
Directly edit the Zend_Form_Element file in the library, -bad for
updates
& other projects that use the librarysubclass Zend_Form_Element and change declaration of the descendants
to
extend new class - same problemsextend each child class and implement those subclasses in your app
code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend
My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to
change.This way developers could "extend" default functionality and have
existing
library classes pick up the new functionality without redeclaring
anything
in the library.Downstream classes would still override any methods that they redeclare.
If
you wanted to have end-point classes in the library have different
behavior,
you would overload them instead, such asclass My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added,
without
me having to touch the library code.I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind
of
behavior... Prototypal languages perhaps, as is the case with javascript
and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.Even though it might look appealing from a framework user perspective,
it looks fishy from a language design perspective. It sounds like
you're trying to fix a framework design lack by a language trick.For the fishy part: what happens to the old class? what about static
method calls on that old class? What if two classes overwrites the
same class? Basically it would mean there is no way to know at compile
time which class new Foo; is supposed to instantiate.Thank you for your comments and thoughts!
Chris Trahey
Web Applications Developer
Database Administrator
CSISD [Technology]
footnote: I sent this message from a different address and it did not
show
up. I tested sending to internals-help@lists.php.net and did not get a
response -so I assume there is an outgoing issue on my other server's
side.
Forgive me if this message shows up again.--
Etienne Kneuss
http://www.colder.ch
The old class is still there, think of it as if the inserted (overloading)
class extends the base (overloaded) class and any classes the were extending
the base now extend the inserted class. So as far as the runtime, it's
run-of-the-meill inheritance. Methods that are not re-implimented in the
inserted class are called in the original class, etc.It could be implemented either at the time a class is loaded (when we see
'overloads' keyword) or perhaps in a function call:
overload_class('Library_Class', 'My_LibClass_Overload');As for conflicts where multiple overloads are attempted, they could be in
sequence, such that you'd end up having an inheritance chain like this:called_class <-- second_overload <-- first_overload <-- Library_Class <--
etc.
In Objective-C, one did this in the older days by calling NSObject's -poseAsClass: method, which would replace the class you sent it to with the class you specified. Nowadays that approach is strongly discouraged in favor of method swizzling, a technique by which you replace a specific class' implementation of a single method with your own (which, with a minor bit of extra work, can call through to the original). Internally, it's done by replacing the function pointer in the class' method table with a new one and returning the old one. Zend's implementation is slightly more twisted than libobjc's, amusingly enough, but it's still doable. This is the typical way for a dynamic language to solve the problem you've described. In PHP I believe the necessary work is already implemented in runkit via the function runkit_method_redefine(). You need only install that, or refer to it to make an extension of your own. If you want this functionality in core, file a feature request. (I'm personally in favor of making a lot of runkit's dynamic class tweaking abilities core).
As far as I understand your issue, this technique would solve it cleanly.
Hi,
On Sat, Mar 13, 2010 at 2:50 AM, Chris Trahey christrahey@gmail.com
wrote:Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.These libraries, while greatly extensible, are also fairly
self-extending.
That is, they include many classes that extend many classes, which is
great.As consumers of these libraries, we can extend the classes and consume
the
API however we please, but there is one sticking point.We cannot change classes that many other classes extend without extending
or
changing each child class and then making sure that our code uses the new
class.For a concrete example, I was working with the Zend_Form_Element
subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want
to
just start changing the Zend library files -There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
Directly edit the Zend_Form_Element file in the library, -bad for
updates
& other projects that use the librarysubclass Zend_Form_Element and change declaration of the descendants
to
extend new class - same problemsextend each child class and implement those subclasses in your app
code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend
My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to
change.This way developers could "extend" default functionality and have
existing
library classes pick up the new functionality without redeclaring
anything
in the library.Downstream classes would still override any methods that they redeclare.
If
you wanted to have end-point classes in the library have different
behavior,
you would overload them instead, such asclass My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added,
without
me having to touch the library code.I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind
of
behavior... Prototypal languages perhaps, as is the case with javascript
and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.Even though it might look appealing from a framework user perspective,
it looks fishy from a language design perspective. It sounds like
you're trying to fix a framework design lack by a language trick.For the fishy part: what happens to the old class? what about static
method calls on that old class? What if two classes overwrites the
same class? Basically it would mean there is no way to know at compile
time which class new Foo; is supposed to instantiate.Thank you for your comments and thoughts!
Chris Trahey
Web Applications Developer
Database Administrator
CSISD [Technology]
footnote: I sent this message from a different address and it did not
show
up. I tested sending to internals-help@lists.php.net and did not get a
response -so I assume there is an outgoing issue on my other server's
side.
Forgive me if this message shows up again.--
Etienne Kneuss
http://www.colder.ch
-- Gwynne
Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.These libraries, while greatly extensible, are also fairly self-extending.
That is, they include many classes that extend many classes, which is great.As consumers of these libraries, we can extend the classes and consume the
API however we please, but there is one sticking point.We cannot change classes that many other classes extend without extending or
changing each child class and then making sure that our code uses the new
class.For a concrete example, I was working with the Zend_Form_Element subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want to
just start changing the Zend library files -There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
Directly edit the Zend_Form_Element file in the library, -bad for updates
& other projects that use the librarysubclass Zend_Form_Element and change declaration of the descendants to
extend new class - same problemsextend each child class and implement those subclasses in your app code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to change.
This way developers could "extend" default functionality and have existing
library classes pick up the new functionality without redeclaring anything
in the library.Downstream classes would still override any methods that they redeclare. If
you wanted to have end-point classes in the library have different behavior,
you would overload them instead, such asclass My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added, without
me having to touch the library code.I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind of
behavior... Prototypal languages perhaps, as is the case with javascript and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.Thank you for your comments and thoughts!
Chris Trahey
I had exactly the same issue with Zend_Soap_AutoDiscover. This class
uses Zend_Soap_Wsdl to create the WSDL file for a SOAP service.
The class was hard coded. The AutoDiscover class allowed you to supply
a class name to handle complex types, but not in conjunction with xsd
scalar types. The Zend_Soap_Wsdl class handled php -> xsd types and
read docblocks for that.
But if the docblock had an xsd type (xsd:datetime, xsd:token, etc.)
which are used to tell the consumer what the type is, then there was
no way to get these in.
So, I created this patch
http://framework.zend.com/code/changelog/Zend_Framework?cs=21379 (diff
http://framework.zend.com/code/browse/Zend_Framework/standard/trunk/library/Zend/Soap/AutoDiscover.php?r1=20096&r2=21379)
which allows me to supply an alternative class name in a similar
fashion to being able to supply a complex type handler class name.
This was the easiest route I could find and the least impacting (full
BC exists).
The amendment I made to allow a subclass to be used as an alternative
is a one off hit, so maybe this technique could be used for Zend_Form
(I assume this is the class you are needing to amend).
Regards,
Richard.
--
Richard Quadling
"Standing on the shoulders of some very clever giants!"
EE : http://www.experts-exchange.com/M_248814.html
EE4Free : http://www.experts-exchange.com/becomeAnExpert.jsp
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
ZOPA : http://uk.zopa.com/member/RQuadling
This is a good use of the decorator pattern. Let's say you don't like the
way Zend_Form_Element filters form names. You can decorate it with a Your
own class which overrides this, and whenever you add a new element to your
form, decorate it with this class.
On Sat, Mar 13, 2010 at 10:10 AM, Richard Quadling <rquadling@googlemail.com
wrote:
Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.These libraries, while greatly extensible, are also fairly
self-extending.
That is, they include many classes that extend many classes, which is
great.As consumers of these libraries, we can extend the classes and consume
the
API however we please, but there is one sticking point.We cannot change classes that many other classes extend without extending
or
changing each child class and then making sure that our code uses the new
class.For a concrete example, I was working with the Zend_Form_Element
subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want
to
just start changing the Zend library files -There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
Directly edit the Zend_Form_Element file in the library, -bad for
updates
& other projects that use the librarysubclass Zend_Form_Element and change declaration of the descendants
to
extend new class - same problemsextend each child class and implement those subclasses in your app
code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend
My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to
change.This way developers could "extend" default functionality and have
existing
library classes pick up the new functionality without redeclaring
anything
in the library.Downstream classes would still override any methods that they redeclare.
If
you wanted to have end-point classes in the library have different
behavior,
you would overload them instead, such asclass My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added,
without
me having to touch the library code.I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind
of
behavior... Prototypal languages perhaps, as is the case with javascript
and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.Thank you for your comments and thoughts!
Chris Trahey
I had exactly the same issue with Zend_Soap_AutoDiscover. This class
uses Zend_Soap_Wsdl to create the WSDL file for a SOAP service.The class was hard coded. The AutoDiscover class allowed you to supply
a class name to handle complex types, but not in conjunction with xsd
scalar types. The Zend_Soap_Wsdl class handled php -> xsd types and
read docblocks for that.But if the docblock had an xsd type (xsd:datetime, xsd:token, etc.)
which are used to tell the consumer what the type is, then there was
no way to get these in.So, I created this patch
http://framework.zend.com/code/changelog/Zend_Framework?cs=21379 (diffhttp://framework.zend.com/code/browse/Zend_Framework/standard/trunk/library/Zend/Soap/AutoDiscover.php?r1=20096&r2=21379
)
which allows me to supply an alternative class name in a similar
fashion to being able to supply a complex type handler class name.This was the easiest route I could find and the least impacting (full
BC exists).The amendment I made to allow a subclass to be used as an alternative
is a one off hit, so maybe this technique could be used for Zend_Form
(I assume this is the class you are needing to amend).Regards,
Richard.
--
Richard Quadling
"Standing on the shoulders of some very clever giants!"
EE : http://www.experts-exchange.com/M_248814.html
EE4Free : http://www.experts-exchange.com/becomeAnExpert.jsp
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
ZOPA : http://uk.zopa.com/member/RQuadling
I also ran into this problem with Zend_Db_Select. I wanted to add a new
constant to improve my usage of Zend_Db_Table#select(), but that method
would always returns an instance of Zend_Db_Table_Select which extended
Zend_Db_Select. There was no easy way for me to add my class constant
without resorting to one of the 3 methods Chris mentioned.
Another possible solution (although it would require a rewrite of the
framework classes) is to avoid using "extends" entirely. This can be
accomplished by using interfaces instead, which is explained in this
article:
http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html
Although the article is a bit dated and it's for Java, the concept still
applies and can help developers make better use of framework code by
inheriting only the implementations they need while providing alternate
implementations when necessary.
Maybe this can be a design paradigm to attempt to follow in ZF 2.0?
--
Hector
On Sat, Mar 13, 2010 at 8:10 AM, Richard Quadling
rquadling@googlemail.comwrote:
Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.These libraries, while greatly extensible, are also fairly
self-extending.
That is, they include many classes that extend many classes, which is
great.As consumers of these libraries, we can extend the classes and consume
the
API however we please, but there is one sticking point.We cannot change classes that many other classes extend without extending
or
changing each child class and then making sure that our code uses the new
class.For a concrete example, I was working with the Zend_Form_Element
subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want
to
just start changing the Zend library files -There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
Directly edit the Zend_Form_Element file in the library, -bad for
updates
& other projects that use the librarysubclass Zend_Form_Element and change declaration of the descendants
to
extend new class - same problemsextend each child class and implement those subclasses in your app
code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend
My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to
change.This way developers could "extend" default functionality and have
existing
library classes pick up the new functionality without redeclaring
anything
in the library.Downstream classes would still override any methods that they redeclare.
If
you wanted to have end-point classes in the library have different
behavior,
you would overload them instead, such asclass My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added,
without
me having to touch the library code.I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind
of
behavior... Prototypal languages perhaps, as is the case with javascript
and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.Thank you for your comments and thoughts!
Chris Trahey
I had exactly the same issue with Zend_Soap_AutoDiscover. This class
uses Zend_Soap_Wsdl to create the WSDL file for a SOAP service.The class was hard coded. The AutoDiscover class allowed you to supply
a class name to handle complex types, but not in conjunction with xsd
scalar types. The Zend_Soap_Wsdl class handled php -> xsd types and
read docblocks for that.But if the docblock had an xsd type (xsd:datetime, xsd:token, etc.)
which are used to tell the consumer what the type is, then there was
no way to get these in.So, I created this patch
http://framework.zend.com/code/changelog/Zend_Framework?cs=21379 (diffhttp://framework.zend.com/code/browse/Zend_Framework/standard/trunk/library/Zend/Soap/AutoDiscover.php?r1=20096&r2=21379
)
which allows me to supply an alternative class name in a similar
fashion to being able to supply a complex type handler class name.This was the easiest route I could find and the least impacting (full
BC exists).The amendment I made to allow a subclass to be used as an alternative
is a one off hit, so maybe this technique could be used for Zend_Form
(I assume this is the class you are needing to amend).Regards,
Richard.
--
Richard Quadling
"Standing on the shoulders of some very clever giants!"
EE : http://www.experts-exchange.com/M_248814.html
EE4Free : http://www.experts-exchange.com/becomeAnExpert.jsp
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
ZOPA : http://uk.zopa.com/member/RQuadling
The challenge of "never use extend" is that simply wrapping classes in
decorators only goes so far. You can't always maintain interface compliance
if you're nesting decorators, and if you're overriding only one out of a dozen
or two methods then you have a lot of foo() { return $obj->foo(); } method
implementations. Aside from being hard to read, that also eats up cycles for
the extra stack calls. __call() can make it much less code but is also much
slower.
If there were a syntactic-level support for "wrap this object in this class
and pass through any method that isn't redefined", a sort of sideways extends,
that would become much simpler. I'm not sure what that would look like,
though.
Or perhaps this is a good time to revisit the traits proposal from a few
months back?
--Larry Garfield
On Monday 15 March 2010 12:36:32 pm Hector Virgen wrote:
I also ran into this problem with Zend_Db_Select. I wanted to add a new
constant to improve my usage of Zend_Db_Table#select(), but that method
would always returns an instance of Zend_Db_Table_Select which extended
Zend_Db_Select. There was no easy way for me to add my class constant
without resorting to one of the 3 methods Chris mentioned.Another possible solution (although it would require a rewrite of the
framework classes) is to avoid using "extends" entirely. This can be
accomplished by using interfaces instead, which is explained in this
article:http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html
Although the article is a bit dated and it's for Java, the concept still
applies and can help developers make better use of framework code by
inheriting only the implementations they need while providing alternate
implementations when necessary.Maybe this can be a design paradigm to attempt to follow in ZF 2.0?
--
HectorOn Sat, Mar 13, 2010 at 8:10 AM, Richard Quadling
rquadling@googlemail.comwrote:
Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading
(or upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries.
In fact, this idea came from my current project using the Zend
Framework.These libraries, while greatly extensible, are also fairly
self-extending.
That is, they include many classes that extend many classes, which is
great.
As consumers of these libraries, we can extend the classes and consume
the
API however we please, but there is one sticking point.
We cannot change classes that many other classes extend without
extendingor
changing each child class and then making sure that our code uses the
new class.For a concrete example, I was working with the Zend_Form_Element
subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't
wantto
just start changing the Zend library files -
There are many subclasses of Zend_Form_Element. If you want to change
the default behavior for all of them, you have 3 choices currently:
- Directly edit the Zend_Form_Element file in the library, -bad for
updates
& other projects that use the library
- subclass Zend_Form_Element and change declaration of the descendants
to
extend new class - same problems
- extend each child class and implement those subclasses in your app
code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend
My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to
change.
This way developers could "extend" default functionality and have
existing
library classes pick up the new functionality without redeclaring
anything
in the library.
Downstream classes would still override any methods that they
redeclare.If
you wanted to have end-point classes in the library have different
behavior,
you would overload them instead, such as
class My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about
the extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added,without
me having to touch the library code.
I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also,
I'm not sure if there are other class-based OO languages that allow
this kindof
behavior... Prototypal languages perhaps, as is the case with
javascriptand
the Obj.prototype which (combined with anonymous functions) allows you
to extend the "base" functionality of other objects that "extend" it.Thank you for your comments and thoughts!
Chris Trahey
I had exactly the same issue with Zend_Soap_AutoDiscover. This class
uses Zend_Soap_Wsdl to create the WSDL file for a SOAP service.The class was hard coded. The AutoDiscover class allowed you to supply
a class name to handle complex types, but not in conjunction with xsd
scalar types. The Zend_Soap_Wsdl class handled php -> xsd types and
read docblocks for that.But if the docblock had an xsd type (xsd:datetime, xsd:token, etc.)
which are used to tell the consumer what the type is, then there was
no way to get these in.So, I created this patch
http://framework.zend.com/code/changelog/Zend_Framework?cs=21379 (diffhttp://framework.zend.com/code/browse/Zend_Framework/standard/trunk/libra
ry/Zend/Soap/AutoDiscover.php?r1=20096&r2=21379 )
which allows me to supply an alternative class name in a similar
fashion to being able to supply a complex type handler class name.This was the easiest route I could find and the least impacting (full
BC exists).The amendment I made to allow a subclass to be used as an alternative
is a one off hit, so maybe this technique could be used for Zend_Form
(I assume this is the class you are needing to amend).Regards,
Richard.
On Mon, Mar 15, 2010 at 2:14 PM, Larry Garfield larry@garfieldtech.comwrote:
The challenge of "never use extend" is that simply wrapping classes in
decorators only goes so far. You can't always maintain interface
compliance
if you're nesting decorators, and if you're overriding only one out of a
dozen
or two methods then you have a lot of foo() { return $obj->foo(); } method
implementations. Aside from being hard to read, that also eats up cycles
for
the extra stack calls. __call() can make it much less code but is also
much
slower.If there were a syntactic-level support for "wrap this object in this class
and pass through any method that isn't redefined", a sort of sideways
extends,
that would become much simpler. I'm not sure what that would look like,
though.Or perhaps this is a good time to revisit the traits proposal from a few
months back?
While traits do seem pretty cool, the fundamental problem appears to be that
Framework X doesn't let me do what I want. Unfortunately that is the side
effect of using a framework, it does things for you. I had attempted to
build a system like this in userland code to dynamically replace classes in
my framework, but scrapped it because I could only see ways in which it
would be abused. If someone replaces a class buried in a framework, that
modifies some bit of functionality, which is depended on by a completely
unrelated area of the framework, it could potentially cause issues that
would be very hard to track down. This sounds a lot like aspect oriented
programming in the ability to completely overwrite a function with userland
code.
I feel like the better solution is to fix the framework to allow the
flexibility to do what you want in a controlled manner, and not bend the
language to fix the framework. I don't mean to say that PHP is problem free
or perfect, but I'm not sure this is the best method to fix the problem at
hand.
--
-Nathan Gordon
If the database server goes down and there is no code to hear it, does it
really go down?
<esc>:wq<CR
On Monday 15 March 2010 03:08:28 pm Nate Gordon wrote:
If there were a syntactic-level support for "wrap this object in this
class and pass through any method that isn't redefined", a sort of
sideways extends,
that would become much simpler. I'm not sure what that would look like,
though.Or perhaps this is a good time to revisit the traits proposal from a few
months back?While traits do seem pretty cool, the fundamental problem appears to be
that Framework X doesn't let me do what I want. Unfortunately that is the
side effect of using a framework, it does things for you. I had attempted
to build a system like this in userland code to dynamically replace
classes in my framework, but scrapped it because I could only see ways in
which it would be abused. If someone replaces a class buried in a
framework, that modifies some bit of functionality, which is depended on
by a completely unrelated area of the framework, it could potentially
cause issues that would be very hard to track down. This sounds a lot
like aspect oriented programming in the ability to completely overwrite a
function with userland code.I feel like the better solution is to fix the framework to allow the
flexibility to do what you want in a controlled manner, and not bend the
language to fix the framework. I don't mean to say that PHP is problem
free or perfect, but I'm not sure this is the best method to fix the
problem at hand.
Certainly true; it's not PHP's job to work around framework flaws. However, if
PHP can make it easier to make frameworks that don't have common flaws, that is
something it can and IMO should do.
Traits wouldn't fix the issue mentioned here, but might allow the framework to
be written in a way that doesn't have, or at least ameliorates, these sorts of
issues.
Or perhaps there's a different approach besides traits that would work better.
I dunno. :-)
--Larry Garfield
On Monday 15 March 2010 03:08:28 pm Nate Gordon wrote:
If there were a syntactic-level support for "wrap this object in this
class and pass through any method that isn't redefined", a sort of
sideways extends,
that would become much simpler. I'm not sure what that would look like,
though.Or perhaps this is a good time to revisit the traits proposal from a few
months back?While traits do seem pretty cool, the fundamental problem appears to be
that Framework X doesn't let me do what I want. Unfortunately that is the
side effect of using a framework, it does things for you. I had attempted
to build a system like this in userland code to dynamically replace
classes in my framework, but scrapped it because I could only see ways in
which it would be abused. If someone replaces a class buried in a
framework, that modifies some bit of functionality, which is depended on
by a completely unrelated area of the framework, it could potentially
cause issues that would be very hard to track down. This sounds a lot
like aspect oriented programming in the ability to completely overwrite a
function with userland code.I feel like the better solution is to fix the framework to allow the
flexibility to do what you want in a controlled manner, and not bend the
language to fix the framework. I don't mean to say that PHP is problem
free or perfect, but I'm not sure this is the best method to fix the
problem at hand.Certainly true; it's not PHP's job to work around framework flaws. However, if
PHP can make it easier to make frameworks that don't have common flaws, that is
something it can and IMO should do.Traits wouldn't fix the issue mentioned here, but might allow the framework to
be written in a way that doesn't have, or at least ameliorates, these sorts of
issues.Or perhaps there's a different approach besides traits that would work better.
I dunno. :-)--Larry Garfield
The ability to "registerASubClassForThisClass" idea (don't know the
proper name for this), has certainly worked for me.
--
Richard Quadling
"Standing on the shoulders of some very clever giants!"
EE : http://www.experts-exchange.com/M_248814.html
EE4Free : http://www.experts-exchange.com/becomeAnExpert.jsp
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
ZOPA : http://uk.zopa.com/member/RQuadling
It seems to me that you could transparently sub-class any framework's base classes with an autoloader implementation... without needing to alter the code that consumes them. You could also "inject" the code as part of your build & test automation. Perhaps you could even make due with an AOP extension to PHP.
Perhaps a new concept in class-based OO programming, I'm not sure.
Depending on your perspective you could call it ancestor overloading (or
upstream overloading) or class underloading.We are increasingly developing with the aid of frameworks & libraries. In
fact, this idea came from my current project using the Zend Framework.These libraries, while greatly extensible, are also fairly self-extending.
That is, they include many classes that extend many classes, which is great.As consumers of these libraries, we can extend the classes and consume the
API however we please, but there is one sticking point.We cannot change classes that many other classes extend without extending or
changing each child class and then making sure that our code uses the new
class.For a concrete example, I was working with the Zend_Form_Element subclasses,
and I realized that I wanted to change some of the default behavior (in
Zend_Form_Element).
- at this point I will assume the reader understands why I wouldn't want to
just start changing the Zend library files -There are many subclasses of Zend_Form_Element. If you want to change the
default behavior for all of them, you have 3 choices currently:
Directly edit the Zend_Form_Element file in the library, -bad for updates
& other projects that use the librarysubclass Zend_Form_Element and change declaration of the descendants to
extend new class - same problemsextend each child class and implement those subclasses in your app code
-very tedious and TONS of repeated code, breaks consistency of API for
developers.There could be a better way, if we could insert a class into the family
tree.And that's the heart of this idea, so I'll repeat it:
- insert a class into the family tree *
Image we do it using an alternative keyword to "extends", such as
"overloads".Example:
class Library_Class { }
class Library_Subclass extends Library_Class {}
and then:
class My_LibClass_Overload overloads Library_Class{}
Now new instances of Library_Subclass actually extend My_LibClass_Overload,
which "extends" Library_Class. The developer would then code
My_LibClass_Overload as if it were declared like this:class Library_Class {}
class My_LibClass_Overload extends Library_Class {}
class Library_Subclass extends My_LibClass_Overload {}
But indeed the declaration of Library_Subclass would not have to change.
This way developers could "extend" default functionality and have existing
library classes pick up the new functionality without redeclaring anything
in the library.Downstream classes would still override any methods that they redeclare. If
you wanted to have end-point classes in the library have different behavior,
you would overload them instead, such asclass My_LibSubclass_Overload overloads Lib_Subclass {}
The benefit is that the application code can still consume "standard"
classes, such as Library_Subclass and not need to know or care about the
extended functionality.Going back to my concrete example, my code could then still use
Zend_Form_Element_Text, but benefit from the modifications I added, without
me having to touch the library code.I hope I've explained clearly what this could look like. I'm a younger
developer, so forgive me if I'm rough on the terminology -perhaps
overload/underload is not the best word for this functionality. Also, I'm
not sure if there are other class-based OO languages that allow this kind of
behavior... Prototypal languages perhaps, as is the case with javascript and
the Obj.prototype which (combined with anonymous functions) allows you to
extend the "base" functionality of other objects that "extend" it.Thank you for your comments and thoughts!
Chris Trahey
Web Applications Developer
Database Administrator
CSISD [Technology]
footnote: I sent this message from a different address and it did not show
up. I tested sending to internals-help@lists.php.net and did not get a
response -so I assume there is an outgoing issue on my other server's side.
Forgive me if this message shows up again.