a simple solution to write an abstract class with the constructor predefinition
interface MyBaseClassAbstract
{
public pleaseDefineThisMethod();
}
class MyBaseClass
{
function __construct()
{
if(get_class($this) == __CLASS__)
throw new Exception("you can't instantiate this class");
else
{
//common constructor
}
}
}
class MyClass extends MyBaseClass implements MyBaseClassAbstract
{
function pleaseDefineThisMethod()
{
echo "hello";
}
}
$test = new MyClass();
$test = new MyBaseClass(); // error!
Klassenabstraktion
PHP 5 führt abstrakte Klassen und Methoden ein. Abstrakt definierte Klassen dürfen nicht instanziiert werden; wurde. Jede Klasse, die wenigstens eine abstrakte Methode enthält, muss ebenso abstrakt sein. Abstrakt definierte Methoden deklarieren nur die Signatur der Methode - sie können nicht die Implementierung definieren.
Wenn eine abstrakte Klasse abgeleitet wird, müssen alle in der Deklaration der Elternklasse abstrakt bezeichneten Methoden durch das Kind definiert werden. Zusätzlich müssen diese Methoden mit derselben (oder einer weniger einschränkenden) Sichtbarkeit definiert werden. Wenn die abstrakte Methode zum Beispiel als protected definiert ist, muss die Funktionsimplementierung entweder als protected oder public, aber nicht private, definiert sein. Außerdem müssen sich die Signaturen der Methoden sich entsprechen, d.h. die Type-Hints und die Anzahl der erforderlichen Parameter müssen gleich sein. Dies gilt seit PHP 5.4 auch für Konstruktoren. Vor 5.4 konnten Konstruktor-Signaturen voneinander abweichen.
Beispiel #1 Beispiel für abstrakte Klasse
<?php
abstract class AbstractClass
{
// Die abgeleitete Klasse zwingen, diese Methoden zu definieren
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Gemeinsame Methode
public function printOut() {
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
ConcreteClass1 FOO_ConcreteClass1 ConcreteClass2 FOO_ConcreteClass2
Älterer Code, der keine nutzerdefinierten Klassen oder Funktionen mit dem Namen 'abstract' besitzt, sollte ohne Änderungen lauffähig sein.
Klassenabstraktion
06-Jul-2007 11:29
26-Jun-2007 03:25
I love examples.
This example will let you see that an Interface and an Astract Class are two different entities.
Just go and read the Object Interface section at :
http://www.php.net/manual/en/language.oop5.interfaces.php
and look at this example
<?php
/*
* A Very simple example to understand why we should use ABSRACT CLASSES.
* This abstract class contains 2 methods : 1 abstract and 1 common methods.
*
*/
abstract class Shape
{
# Let's assume a shape will always have a base and a height
protected $base;
protected $height;
#This function can be the same for both classes 'Triangle' and 'Rectangle'
public function getValue($base,$height)
{
$this->base = $base;
$this->height = $height;
}
# This might be different for each class of shape, because each Surface is calculated by a different formula ( St = b*h/2 and Sr = b*h)
abstract public function surface();
}
class Triangle extends Shape
{
# s = b*h/2
public function surface(){
return round((($this->base)*($this->height)/2),2);
}
}
class Rectangle extends Shape
{
# s = b*h
public function surface(){
return round((($this->base)*($this->height)),2);
}
}
$r = new Rectangle();
$r->getValue(15,3);
echo $r->surface() ."\n"; # echo 45
$t = new Triangle();
$t->getValue(15,3);
echo $t->surface() ."\n"; # echo 22.5
?>
24-Jun-2007 01:09
I don't agree with jfkallens' last comparison between Abstract Classes & Object Interfaces completely.
In an Abstract Class, you can define how some methods work, where as in an Object Interface you can not.
An Object Interface is essentually nothing but a list of function names that a class must define if the class implements that interface.
An Abstract Class is essentually a prototype which hints towards what extending classes should be doing.
An Abstract Class can also be thought of as a Base Class that provides some basic functionality, & also defines a built-in Object Interface that all extending classes will implement.
So, an Object Interface is really a built-in part of an Abstract Class.
11-Jun-2007 05:25
A couiple of years ago I raised the question on this website as to what the difference between an interface and an abstract class is. At some point I learned how to define the words for myself since then - and now all is clear :)
An interface allows you to define what is conceptually the same thing as an abstract class except that all methods are public. That makes sense as an "interface" represents how an app or environment interacts with the object - normally via public methods.
25-Jul-2006 05:27
It took me a while to figure this out and i couldn't find it easily in the documentation anywhere.
If you want to override a method from a base class and want to call the base class in the method, then you have to use the parent::function() syntax, even though the method isn't static. There is no $base variable in php that i know of.
Expamle:
<?php
public abstract class BasePerson() {
/*
* alot of code..
*/
public function getName() {
return $this->name;
}
}
public class Person() extends BasePerson {
/*
* alot of code..
*/
// override of base getName()..
public function getName() {
// you would expect $base->getName() instead of parrent::getName()...
return htmlspecialchars(parent::getName());
}
}
?>
Hope this helps!
16-May-2006 07:10
A nice tutorial on PHP5's abstract classes and interfaces:
Working with php5 class types abstract classes and interfaces.
http://www.phpfive.net/article4.htm
06-Mar-2006 02:48
Abstract classes allow the declaration of protected abstract methods, which cannot be emulated with the use of an interface and a concrete superclass.
Even private abstract methods can be declared, although I fail to see the use in them, as subclasses will not see them anyway.
28-Dec-2005 10:27
Variable-length argument lists in abstract methods will generate fatal error if derived. Here is an simple example:
<?php
// common wrap for all validators is forcing uniform interface
abstract class ValidatorWrap {
// just example why variable-length arguments are needed
public function __construct()
{
if (func_num_args() > 0) {
$arg_list = func_get_args();
call_user_func_array(array(&$this, 'setupValidator'), $arg_list);
} else {
$this->setupValidator();
}
// continue with construction
}
// amount of arguments is specific to validator implementation
abstract public function setupValidator();
// known interface
abstract public function validate($value);
}
class Validator1 extends ValidatorWrap {
protected $pattern = '';
// this will generate PHP Fatal error because $pattern is not expected
public function setupValidator($pattern)
{
$this->pattern = $pattern;
}
// this will do OK
public function validate($value)
{
return preg_match($this->pattern, $value);
}
}
// make numeric validator
$validator = new Validator1('/^\d+$/');
echo (int) $validator->validate($_REQUEST['digits']);
?>
I need it to work so I just redefine troublemaking function as follows:
<?php
public function setupValidator() { }
?>
This will give me functionality I need and generates only PHP Strict Standards warning.
02-Dec-2005 06:38
<?php
// Design Pattern ABSTRACT FACTORY implementation //
abstract class AbstractFactory {
public abstract function CreateProductA(); // return data type is AbstractProductA
public abstract function CreateProductB(); // return data type is AbstractProductB
}
// Abstract factory #1 //
class ConcreteFactory1 extends AbstractFactory {
public function CreateProductA() { // return data type is AbstractProductA
return new ProductA1();
}
public function CreateProductB() { // return data type is AbstractProductB
return new ProductB1();
}
}
// Abstract factory #2 //
class ConcreteFactory2 extends AbstractFactory {
public function CreateProductA() { // return data type is AbstractProductA //
return new ProductA2();
}
public function CreateProductB() { // return data type is AbstractProductB //
return new ProductB2();
}
}
// "AbstractProductA" //
abstract class AbstractProductA {
}
// "AbstractProductB" //
abstract class AbstractProductB {
public abstract function Interact($a); // return type is void // // input type is AbstractProductA
}
// "ProductA1" //
class ProductA1 extends AbstractProductA {
}
// "ProductB1" //
class ProductB1 extends AbstractProductB {
public function Interact($a) {
echo __CLASS__." interacts with ".__METHOD__."\n";
var_dump($a);
}
}
// "ProductA2"
class ProductA2 extends AbstractProductA {
}
// "ProductB2"
class ProductB2 extends AbstractProductB {
public function Interact($a) {
echo __CLASS__." interacts with ".__METHOD__."\n";
var_dump($a);
}
}
class Client {
private $AbstractProductA; // type AbstractProductA;
private $AbstractProductB; // type AbstractProductB;
// Constructor
public function __construct($factory) {
$this->AbstractProductB = $factory->CreateProductB();
$this->AbstractProductA = $factory->CreateProductA();
}
public function Run() {
$this->AbstractProductB->Interact($this->AbstractProductA);
}
}
// Abstract factory #1
$factory1 = new ConcreteFactory1();
$c1 = new Client($factory1);
$c1->Run();
// Abstract factory #2
$factory2 = new ConcreteFactory2();
$c2 = new Client($factory2);
$c2->Run();
// TURGUT Z. YESILYURT, MS
// Software Developer
// NewJersey, USA
?>
Output::
ProductB1 interacts with ProductB1::Interact
object(ProductA1)#4 (0) {
}
ProductB2 interacts with ProductB2::Interact
object(ProductA2)#8 (0) {
}
07-Nov-2005 06:04
just RE: ramonzamora at gmail dot com
Abstraction is 'stricter' than inheritance+implementation as it contains 'rules' about the visibility of the methods that are inherited, as well as the fact that it saves needing two classes to get a job done.
The fact you cannot instantiate an abstract class can be benificial also.
28-Aug-2005 12:46
so abstract clases are the same than inheritance+interfaces??
<?php
//using inheritance+interfaces
interface callA{
protected function callA();
}
class callB{
protected $b;
protected function callB(){
return $this->b;
}
}
class caller extends callB implements callA{
protected $a;
public function __construct($a,$b){
$this->a=$a;
$this->b=$b;
}
protected function callA(){
return $this->a;
}
public function callAB(){
return $this->callA().$this->callB();
}
}
$caller=new caller('a','b');
$caller->callAB();
//using abstract class
abstract class callAB{
abstract protected function callA();
protected $b;
protected function callB(){
return $this->b;
}
}
class caller extends callAB{
protected $a;
public function __construct($a,$b){
$this->a=$a;
$this->b=$b;
}
protected function callA(){
return $this->a;
}
public function callAB(){
return $this->callA().$this->callB();
}
}
$caller=new caller('a','b');
$caller->callAB();
?>
the only difference i see is that using inheritance+interfaces you can instantiate the parent but using abstract classes you can't