抽象类定义概述
抽象类不能被实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以继承它并且通过实现其中的抽象方法,使抽象类具体化。
我们可以用一个abstract关键字来定义一个抽象类,示例如下:
abstract class Animal {
//抽象类中可以定义属性
protected $animal = 'animal';
//抽象类中也可以定义非抽象方法
public function printit($name) {
$this->animal = $name;
echo $animal;
}
}
由上可见,抽象类和普通类一样,都可以创建方法和属性,那么抽象类可以像普通类那样被实例化吗?我们试一下,实践出真知:
<?php
abstract class Animal {
protected $animal = 'animal';
public function printit($name) {
$this->animal = $name;
echo $animal;
}
}
$Animal = new Animal();
运行结果:Fatal error: Cannot instantiate abstract class Animal in D:\Program Files\wamp\www\a.php on line 10
运行结果显示,不能实例化抽象类Animal,现在知道咯,抽象类不能像普通类那样被实例化的哟。
下面来讨论一下抽象类内的抽象方法
抽象方法用abstract关键字声明,其中不能有具体内容。你可以像声明普通类方法那样声明抽象方法,但要以分号而不是方法体结束。
而在大多数情况下,抽象类中至少要有一个抽象方法,否则这个抽象类也就没有抽象的意义了,也就是说,这个抽象类内可以没有抽象方法只有普通方法,但是,你也没必要将这个类声明称抽象类了,直接去掉abstract变成普通类就行了。
像下面这段代码,就创建了一个抽象类和内部抽象方法:
abstract class Animal {
//属性
protected $animal = 'animal';
//普通方法
public function printit($name) {
$this->animal = $name;
echo $animal;
}
//抽象方法,以分号结束,无方法体;抽象类中至少要有一个抽象方法
abstract public function setit();
}
那么,一个类中只有抽象方法而这个类不是抽象类可以吗?试验一下:
<?php
class Animal {
protected $animal = 'animal';
public function printit($name) {
$this->animal = $name;
echo $animal;
}
abstract public function setit();
}
运行结果:Fatal error: Class Animal contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Animal::setit) in D:\Program Files\wamp\www\a.php on line 9
结果显示了一个致命的错误,说类Animal包含了一个抽象方法,所以这个类必须被声明为抽象类或者实现有抽象方法setit()的类。
继承抽象类并实现抽象方法
创建抽象方法后,要确保所有子类中都实现可该方法,但实现的细节可以先不确定。
如果创建了一个继承自抽象类Animal的普通类,但是不实现其中的抽象方法,会发生什么呢?看下面的这段代码:
<?php
abstract class Animal {
protected $animal = 'animal';
public function printit($name) {
$this->animal = $name;
echo $animal;
}
abstract public function setit();
}
class Fish extends Animal {
}
运行结果:Fatal error: Class Fish contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Animal::setit) in D:\Program Files\wamp\ w\a.php online 13
这个和只有抽象方法没有把类定义为抽象类发生的错误一样,所以抽象类的每个子类必须实现抽象类中的所有抽象方法,或者把他们自身也声明为抽象方法。
扩展类不仅仅负责简单实现抽象类中的抽象方法,还必须重新声明方法。新的方法的访问控制不能比抽象方法的访问控制更严格。新的实现方法的参数个数应该和抽象方法的参数个数一样,重新生成对应的类型提示。
我们先来定义一个继承自抽象类Animal的子类:
1>
场景:Fish子类中的setit()方法中包含参数;
验证:新的实现方法的参数个数应该和抽象方法的参数个数一样;
<?php
abstract class Animal {
protected $animal = 'animal';
public function printit($name) {
$this->animal = $name;
echo $animal;
}
abstract public function setit();
}
class Fish extends Animal {
//子类中实现抽象方法的函数和抽象类中方法的参数不一致
public function setit($name) {
echo $name;
}
}
运行结果:Fatal error: Declaration of Fish::setit() must be compatible with Animal::setit() in D:\Program Files\wamp\www\a.php on line 15
2>
场景:Fish子类中的setit()方法被声明为private;
验证:新的方法的访问控制不能比抽象方法的访问控制更严格。
(1) 如果 Animal 中 setit() 声明为 public ,那么 Fish 中 setit() 的声明只能是 public ,不能是 protected 或 private ;
(2) 如果 Animal 中 setit() 声明为 protected ,那么 Fish 中 setit() 的声明可以是 public 或 protected ,但不能是 private ;
(3) 如果 Animal 中 setit() 声明为 private ,嘿嘿,不能定义为 private 哦!( Fatal error : Abstract function Animal ::setit() cannot be declared private ) —–引自http://blog.csdn.net/sunlylorn/article/details/6124319
<?php
abstract class Animal {
protected $animal = 'animal';
public function printit($name) {
$this->animal = $name;
echo $animal;
}
abstract public function setit();
}
class Fish extends Animal {
//子类中的实现方法被声明为private和抽象类中的方法声明不一致
private function setit($name) {
echo $name;
}
}
运行结果:Fatal error: Access level to Fish::setit() must be public (as in class Animal) in D:\Program Files\wamp\www\a.php on line 15
推荐书籍:《深入PHP面向对象、模式与实践》