Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.
class A {
public function getToken() { return "a"; }
}
class B extends A {
public function getToken() { return "b"; }
}
class C extends B {
public function getToken() { return "c"; }
}
$a = new A();
$b = new B();
$c = new C();
I'm looking for the best way to implement a method that would behave like this:
A::allTokens($a); // returns "a"
A::allTokens($b); // returns "a b"
A::allTokens($c); // returns "a b c"
Thanks, but that's not exactly what I'm looking for. The point is that I want to place the function in the base class A, so that child classes only need to define their own getToken() function. The goal is to find a design that doesn't rely on a convention (such as using super and appending the return value).
It's a design question, not a howto question. The base class is meant to be part of an API, and the child classes are hypothetical classes that a user of the API would implement. I want the functionality to be achieved without requiring a user of the API to follow any unnecessary conventions.
~pickle | Please use [ code=html ], [ code=php ], etc tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: Posting Code in the Forums to learn how to do it too.
For what it's worth, here's the design I decided to go with
class A {
private $tokens;
function __construct() {
$tokens = array();
$this->addToken('a');
}
protected function addToken($token) {
$tokens[] = $token;
}
public function getTokens() {
return $tokens;
}
}
class B extends A {
function __construct() {
parent::__construct();
$this->addToken('b');
}
}
class C extends B {
function __construct() {
parent::__construct() {
$this-addToken('c');
}
}
It doesn't behave exactly as I described, but works for what I needed and doesn't require people writing sub classes to do anything too confusing.
~pickle | Please use [ code=html ], [ code=php ], etc tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: Posting Code in the Forums to learn how to do it too.
You could use the observable pattern so the parent class can just fire off an "event" and have the child classes attach themselves to the trigger, so the base class doesn't have to know about the other classes
class Toker {
protected $tokens = array();
public function addToken($token) {
$this->tokens[] = $token;
}
public function getTokens() {
$str = '';
foreach ($this->tokens as $token) {
$str .= $token->getToken();
}
return $str;
}
}
class A {
public function getToken() { return "a"; }
}
class B {
public function getToken() { return "b"; }
}
class C {
public function getToken() { return "c"; }
}
$toker = new Toker();
$toker->addToken(new A());
$toker->addToken(new B());
$toker->addToken(new C());
echo $toker->getTokens();
Thanks arborint! I think this is the "right way" to do what I wanted with OO design. I think I'll go an extra step and make Toker a singleton so that the user doesn't need to bother instantiating it.
As you say your developing API I would suggest think from this users point of view...how will API be used...what is best interface to it.
Don't bother for implementation at first.
philentropist wrote:Thanks arborint! I think this is the "right way" to do what I wanted with OO design. I think I'll go an extra step and make Toker a singleton so that the user doesn't need to bother instantiating it.
That's a horrible reason to adapt the Singleton pattern, or worse yet, not a reason at all. Keep in mind that static functions have their downfalls and you shouldn't introduce them into your software without considering alternatives. Global access comes with a cost: the disability to test, because of the (extremely tight) coupling.
The only thing Singleton is good for, is limiting the number of instances, and to be honest: I think it's even doing a bad job at that. Limiting the number of instances could (and probably should) be done using a Factory or a Builder, without the problems that are inherent to static functions.