The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Going around language (no multiple inheritance)

Darn, I need a class structure that's more or less:

class A
class B
class C extends A, B
class D extends A

But the language doesn't support multiple inheritance.

How do you go around such limitations?

I wouldn't like to use
class A
class B extends A
class C extends B
class D extends A
Because "B" "is a" "A" does not make sense.

The language is PHP.

Thanks.
Cod3rOfPHP
Wednesday, August 15, 2007
 
 
If you describe what you're trying to model, it might be easier to suggest an appropriate technique.
clcr
Wednesday, August 15, 2007
 
 
Agreed.

If C has to have elements of A and B, then C typically contains A and B as internal data structures, and either exposes or hides method calls. For example, if both A and B have a getName() method, then C has to decide what should happen when you call C.getName(). C can chose to only return A.getName(), only B.getName(), combine the two or return something else entirely.

Depending on what you're hoping for or as clcr puts it, what you're trying to model, PHP may have a built in rule to accomplish that without treating A and B as internal data within C.
TheDavid
Wednesday, August 15, 2007
 
 
The purpose is code reuse.

There are classes that are related. And there are functions that are useful in both classes. So C1 and C2 would have a super class called C1C2. This works with single inheritance. The problem is when C1 has a relation with another class that also needs code reuse.

Thanks.
Cod3rOfPHP
Wednesday, August 15, 2007
 
 
I don't know if PHP supports them, but protocols/interfaces are the common replacement for multiple inheritance. Otherwise, you could implement a has-a relationship rather than an is-a relationship with one or both of the ancestors and pass method calls to the contained objects (current OO/patterns design philosophy is to prefer composition to inheritance anyway).

The protocol/interface method just makes it easier to treat a thing as the protocol/interface class from a syntactic standpoint, it doesn't get you implementation (you must implement all the protocol/interface behavior in the class that adopts the protocol/interface).

The composition method doesn't let you treat the object as either of the type of objects that it contains, but it lets you use existing behaviors. You still have to write a bunch of shell methods that delegate to the contained objects.

All that said, I don't quite see how it can make any less sense for B to inherit from A than for C to inheric from both A and B. Of course, I haven't drunk the kool-aid on multiple inheritance.
Jeffrey Dutky Send private email
Wednesday, August 15, 2007
 
 
I'm not sure whether PHP has or will get "mixin" support. But in Ruby and JavaScript I do it like this:

class A
module B
class C extends A
  includes B
class D extends A
Joao Pedrosa
Wednesday, August 15, 2007
 
 
Interfaces dont work because the purpose is code reuse. Composition / "has a" would work but would reduce simplicity (those "shell methods").

"All that said, I don't quite see how it can make any less sense for B to inherit from A than for C to inheric from both A and B."

Example:

Class A
Class B
Class C extends A, B
Class D extends A

Now just add a Class E that's sharing code with class C:

Class E extends B

Using the "B extends A":

Class A
Class B extends A
Class C extends B
Class D extends A
*and*
Class E extends B

Class E now has methods from A which are not related to it.

Thanks.
Cod3rOfPHP
Wednesday, August 15, 2007
 
 
You can use the Delegation pattern. I don't know if PHP has built-in support for this, like Smalltalk's doesNotUnderstand message. If not, then you're pretty much stuck with creating a set of small "shell" methods that call out to contained objects of the two "parent" classes. That's a little ugly, but at least it's very little code, and simple to write.

In a language with a pre-processor (like most C-based languages), you could make a macro that generated the appropriate shells, which would neaten up the code a bit.

At some point, I've really got to read up on PHP...
Mark Bessey Send private email
Wednesday, August 15, 2007
 
 
"You can use the Delegation pattern. I don't know if PHP has built-in support for this, like Smalltalk's doesNotUnderstand message."

Like this ?
http://www.zend.com/zend/php5/php5-delegation.php

I still dont know some of this "new" OOP stuff in PHP5. I come from PHP4 and I'm using my current project to get up to date with this.
Cod3rOfPHP
Wednesday, August 15, 2007
 
 
A little hacky, but can't you just include php files with the methods in php files?
Grant Send private email
Thursday, August 16, 2007
 
 
Cod3rOfPHP: You should resist the temptation to use inheritance as a way of reusing code. It will end up biting you, since it will lock you into a particular chain of inheritance.

Instead, try to write self-contained objects that have more narrowly-defined functionality. Then you can use those objects from other objects. For example:
 class Database {
  protected $logger;
  function __construct(Logger $logger) {
    $this->logger = $logger;
  }
  function log($str) {
    $this->logger->log($str);
  }
  ...
 }

This may be one of those lessons that you have to learn the hard way, though.
JW
Thursday, August 16, 2007
 
 
"Cod3rOfPHP: You should resist the temptation to use inheritance as a way of reusing code. It will end up biting you, since it will lock you into a particular chain of inheritance."

Strongly agree.

Inheritance is about the relationship between classes FROM THE CALLER'S PERSPECTIVE, not about implementation convenience. Design the interface of your classes from the perspective of using them, not implementing them.

Unless C is-a A and C is-a B, it should not inherit from those classes. If you find yourself tempted to use inheritance as a code reuse mechanism in situations where the is-a relationship doesn't hold from the caller's perspective, use delegation instead.
clcr
Thursday, August 16, 2007
 
 
JW: "This may be one of those lessons that you have to learn the hard way, though."

Heh. I certainly had to. I can't remember where I read it (may have been browsing C2) but it was pointed out that all the emphasis on inheritance in OOP books and tutorials gives the wrong impression that it's mostly _about_ inheritance. The rule of thumb I took out of it was that if you can implement it as a has-a relationship, that's probably the right way to do it.

My classes got smaller, less tightly coupled, and I suddenly had to copy and paste a lot less code.
dwayne Send private email
Thursday, August 16, 2007
 
 
I agree that trying to use inheritance to reuse code is bad. It took me quite a while to be convinced of this, but now I'm very strict about only using inheritance for genuine "is-a" relationships.

What I would suggest for your case (without knowing specifics) is:

Make an interface X that A implements;
Make an interface Y that B implements;

Class C implements both X and Y, and CONTAINS an instance of both A and B (acting as a Facade pattern with respect to each).

There are plenty of other ways of doing this. I recommend searching "mixin" (and your language of choice) for more info.
DJ Clayworth
Thursday, August 16, 2007
 
 
Something involving __call() (http://uk3.php.net/manual/en/language.oop5.overloading.php) or runkit (http://uk.php.net/runkit) are about your only options, neither are particularly 'pleasant'.
G Jones Send private email
Thursday, August 16, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz