...

View Full Version : Abstract problem..



funnymoney
08-23-2009, 01:52 PM
I'm trying to implement abstract class to certain number of classes but i have simple problem with this piece of code


abstract Class Implementations {

public function __construct() {
$this->implementMain = new Main();
}

}

Class Main {
public function main() {
return "Do something in method main() class Main";
}
}

Class Sub extends Implementations {

public function sub() {
return $this->implementMain->main();
}

}
$sub = new Sub;

print($sub->sub());


while this sloppy code works




abstract Class Implementations {

public function implementMain() {
return new Main();
}
}

Class Main {
public function main() {
return "Do something in method main() class Main";
}
}

Class Sub extends Implementations {

public function sub() {
return $this->implementMain()->main();
}

}
$sub = new Sub;

print($sub->sub());

Fou-Lu
08-23-2009, 11:26 PM
You have a bc (backwards compatibility) issue. There is nothing wrong with you're code, its the naming convention:


Class Sub extends Implementations {

public function sub() {
return $this->implementMain->main();
}

}

Prior to PHP5, constructors used the naming convention of the class name. Since PHP uses caseless method and function names, the Sub::sub is considered its constructor therefore overriding the constructor declared in abstract implementation.
Fix by either calling parent::__construct, by renaming the sub method, or by declaring an explicit __construct in sub that calls the parent::__construct. The recommended solution is to rename the sub to prevent bc break on PHP4.
You should also be declaring you're $implementMain in abstract implementation. This is especially true since you're dealing with an object which simulates pass by reference using an object pointer (not quite the same as reference, but PHP doesn't actually support pointers anyway). So you have a public member that can be altered from any scope with any call which will create a privacy leak:


abstract Class Implementations {

protected $implementMain;
public function __construct() {
$this->implementMain = new Main();
}

}

Also, without any abstract methods inside of the abstract class, you may as well create a concrete class to extend off of.

funnymoney
08-24-2009, 09:26 AM
ah.. now i get it...
i edited my mistake where i tried again.. lol, i changed both class name Sub and method sub to same Subz and subz so then i've again overwritten constructor. lol

Thanks!!!!

And as for abstract methods, well first lemme ad this bit of abstraction to me classes, so then i can check out weather i can pull out even some abstract methods out of them.

OOP is FUN :)

one more question why did you add that protected $implementMain var, does it have any purpose, or you added it just to know that this class's construct creates that variable?

Fou-Lu
08-24-2009, 09:58 AM
The naming is still the same. The class name cannot match the name of the method in use, otherwise it considers it the constructor.
Scope resolution allows you to use parent and self refering to the object context rather than the static context (which is interesting since it technically applies to the static context as well).
So if you override you're constructor, PHP requires an explict call to the parent constructor:


class MyClass
{
public function __construct()
{
print 'Hello world from: ' . get_class($this);
}
}

class MyChild extends MyClass
{
}

new MyChild(); // Prints 'Hello world from: MyChild
// On the other hand:
class MyChild extends MyClass
{
public function __construct()
{
print 'Goodbye';
}
}
new MyChild(); // Prints 'Goodbye'.

class MyChild extends MyClass
{
public function __construct()
{
parent::__construct();
print '. Goodbye';
}
}
new MyChild(); // Prints 'Hello world from: MyChild. Goodbye


A practical implementation for abstract models is a shape:


abstract class Shape
{
// Add a whole pile of members
public abstract function getArea();
}

class Square extends Shape
{
private $fDimension;
public function __construct($fDim)
{
$this->fDimension = $fDim;
}
public function getArea()
{
return pow($this->fDimension, 2);
}

}

class Circle extends Shape
{
private $fRadius;
public function __construct($fRadius)
{
$this->fRadius = $fRadius;
}
public function getArea()
{
return M_PI * pow($this->fRadius, 2);
}
}


function showArea(Shape $s)
{
printf("Area of %s is %0.5f\n", get_class($s), $s->getArea());
}

$s = new Square(4);
$c = new Circle(3);

showArea($s); // Area of Square is 16.0
showArea($c); // Area of Circle is 28.26


Untested.

That help?


Snuck in an edit there you did :P
protected $implementMain forces predeclaration of you're variables, which is good practice. On top of that, when an unrecognized variable is declared in a class (using just $this->var = whatever) and it has not been predeclared, it takes the scope of public. This actually bothers me to no end about PHP's handling of OO models. Anyway, protected is in use since public is too open and private restricts the child class' ability to view the declared member. Protected scope is defined as 'this' class and any of its subclasses.

funnymoney
08-24-2009, 11:12 AM
Snuck in an edit there you did :P
I was testing and testing, and rereading your post, then i figured out that PHP 4 glitch and edited me stupid class and method renaming :)

for understanding abstract classes i will use Occam's razor (http://en.wikipedia.org/wiki/Occam%27s_razor). most simple solution is one that abstraction is used to force extended classes to use abstracted methods.

other than that i can't see any other solution, and what's sad for me it doesn't solve me problem.

i mean, it really isn't a problem, i was just looking for more elegant solution, but now it looks that there is no better solution than one i'm doing already.

if you want to know what's it about here's the example



<?php

class Mainclass {

public function maindo() {
return "Mainclass::maindo()";
}

}

Class Firstclass {
public function __construct($construct) {
$this->mainclass = new Mainclass();

$this->construct = $construct;
}

public function method() {
return $this->construct ." depends on ". $this->mainclass->maindo() ."<br>\n";
}
}

Class Secondclass {
public function __construct($construct) {
$this->mainclass = new Mainclass();

$this->construct = $construct;
}

public function method() {
return $this->construct ." depends on ". $this->mainclass->maindo() ."<br>\n";
}
}

$x = new Firstclass("Firstclass");
$y = new Secondclass("Secondclass");

print $x->method();
print $y->method();

?>



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum