PHP中的抽象类是什么?

148

什么是PHP中的抽象类?

它怎么使用?


1
请参考以下网址:http://de2.php.net/manual/zh/language.oop5.abstract.php - Gordon
2
抽象类的目的是什么? - Gordon
7
有时候官方文档并不那么清晰易懂,会让一些人感到困惑。@Gordon - Sarfraz
2
抽象关键字在PHP中的作用 - Gordon
4
@Sarfraz,这并不是RTFM方式的意思。我只是认为提供官方文档链接是一个有用的资产。你无法想象有多少人不阅读官方文档甚至不知道其存在。 - Gordon
6个回答

152

抽象类是一种包含至少一个抽象方法的类,该方法没有任何实际代码,只有名称和参数,并被标记为“抽象的”。

其目的是提供一种继承模板,并强制继承类实现抽象方法。

因此,抽象类介于常规类和纯接口之间。也可以将接口看作是所有方法都是抽象的特殊情况的抽象类。

有关更多信息,请参见PHP手册中的此部分。


8
这个帖子中,摘要部分没有包含任何抽象方法。 - r0n9
9
更准确的说法是抽象类可以包含抽象方法,而抽象方法必须始终位于抽象类中。在我看来,抽象类的定义特征是不能实例化,但可以继承和覆盖方法,抽象类中的静态方法可以正常使用。 - okdewit

141

抽象类是包含一个或多个抽象方法的类。抽象方法是声明但不包含实现的方法。抽象类不能被实例化,需要子类为抽象方法提供实现。

1. 无法实例化抽象类 : 定义为抽象的类不能被实例化,任何包含至少一个抽象方法的类必须也是抽象的。

以下是示例:

abstract class AbstractClass
{

    abstract protected function getValue();
    abstract protected function prefixValue($prefix);


    public function printOut() {
        echo "Hello how are you?";
    }
}

$obj=new AbstractClass();
$obj->printOut();
//Fatal error: Cannot instantiate abstract class AbstractClass

2. 任何包含至少一个抽象方法的类都必须是抽象类:抽象类可以同时包含抽象方法和非抽象方法,但必须至少包含一个抽象方法。如果一个类有至少一个抽象方法,则该类必须声明为抽象类。

注意:特质支持使用抽象方法以对展示类施加要求。

例子如下:

class Non_Abstract_Class
{
   abstract protected function getValue();

    public function printOut() {
        echo "Hello how are you?";
    }
}

$obj=new Non_Abstract_Class();
$obj->printOut();
//Fatal error: Class Non_Abstract_Class contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Non_Abstract_Class::getValue)

3. 抽象方法不能包含具体实现: 抽象方法仅声明方法的签名,而不能定义实现。但是,非抽象方法可以定义实现。

abstract class AbstractClass
{
   abstract protected function getValue(){
   return "Hello how are you?";
   }

    public function printOut() {
        echo $this->getValue() . "\n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";
//Fatal error: Abstract function AbstractClass::getValue() cannot contain body

4. 当从抽象类继承时,必须定义父类声明中标记为抽象的所有方法:如果您继承了一个抽象类,则必须为其中的所有抽象方法提供实现。

abstract class AbstractClass
{
    // Force Extending class to define this method
    abstract protected function getValue();

    // Common method
    public function printOut() {
        print $this->getValue() . "<br/>";
    }
}

class ConcreteClass1 extends AbstractClass
{
    public function printOut() {
        echo "dhairya";
    }

}
$class1 = new ConcreteClass1;
$class1->printOut();
//Fatal error: Class ConcreteClass1 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (AbstractClass::getValue)

5. 相同或更宽松的可见性: 当从抽象类继承时,必须定义父类声明中标记为abstract的所有方法;此外,这些方法必须使用相同(或更宽松)的可见性进行定义。例如,如果将抽象方法定义为受保护的,则函数实现必须定义为受保护或公共,但不能是私有的。

注意抽象方法不应为私有方法。

abstract class AbstractClass
{

    abstract public function getValue();
    abstract protected function prefixValue($prefix);

        public function printOut() {
        print $this->getValue();
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."<br/>";
//Fatal error: Access level to ConcreteClass1::getValue() must be public (as in class AbstractClass)

6. 抽象方法的签名必须匹配:当继承抽象类时,父类声明中标记为抽象的所有方法都必须由子类定义;方法的签名必须匹配,即类型提示和所需参数的数量必须相同。例如,如果子类定义了一个可选参数,而抽象方法的签名没有,则签名上不存在冲突。

abstract class AbstractClass
{

    abstract protected function prefixName($name);

}

class ConcreteClass extends AbstractClass
{


    public function prefixName($name, $separator = ".") {
        if ($name == "Pacman") {
            $prefix = "Mr";
        } elseif ($name == "Pacwoman") {
            $prefix = "Mrs";
        } else {
            $prefix = "";
        }
        return "{$prefix}{$separator} {$name}";
    }
}

$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "<br/>";
echo $class->prefixName("Pacwoman"), "<br/>";
//output: Mr. Pacman
//        Mrs. Pacwoman

7. 抽象类不支持多重继承:抽象类可以继承另一个抽象类,也可以提供接口的实现。但是它不支持多重继承。

interface MyInterface{
    public function foo();
    public function bar();
}

abstract class MyAbstract1{
    abstract public function baz();
}


abstract class MyAbstract2 extends MyAbstract1 implements MyInterface{
    public function foo(){ echo "foo"; }
    public function bar(){ echo "bar"; }
    public function baz(){ echo "baz"; }
}

class MyClass extends MyAbstract2{
}

$obj=new MyClass;
$obj->foo();
$obj->bar();
$obj->baz();
//output: foobarbaz
请注意,在您的代码中,类的顺序或定位可能会影响解释器并导致致命错误。 因此,在使用多层抽象时,请小心类在源代码中的定位。 以下示例会导致致命错误:“找不到类'horse'”。
class cart extends horse {
    public function get_breed() { return "Wood"; }
}

abstract class horse extends animal {
    public function get_breed() { return "Jersey"; }
}

abstract class animal {
    public abstract function get_breed();
}

$cart = new cart();
print($cart->get_breed());

如果我们采取第6步,只需在子类中的函数名称的首字母大写。代码将正确运行 - 为什么呢? ... class ConcreteClass extends AbstractClass { public function PrefixName($name, $separator = ".") { ... } ... - Mykola

19
抽象类是部分实现的类,可能包含一个或多个抽象方法。抽象方法仅是函数定义,告诉程序员该方法必须在子类中实现。
有关此内容的好解释可以在这里找到。

嗨,感谢您的解释,事实上在互联网上关于PHP中抽象和接口的解释没有这么好的。 - Lenin Zapata

13

抽象类
1. 包含一个抽象方法
2. 不能直接初始化
3. 不能创建抽象类的对象
4. 只用于继承目的

抽象方法
1. 不能包含主体
2. 不能定义为私有的
3. 子类必须定义在抽象类中声明的方法

示例代码:

abstract class A {
    public function test1() {
        echo 'Hello World';
    }
    abstract protected function f1();
    abstract public function f2();
    protected function test2(){
        echo 'Hello World test';
    }
}

class B extends A {
    public $a = 'India';
    public function f1() {
        echo "F1 Method Call";
    }
    public function f2() {
        echo "F2 Method Call";
    }
}

$b = new B();
echo $b->test1() . "<br/>";
echo $b->a . "<br/>";
echo $b->test2() . "<br/>";
echo $b->f1() . "<br/>";
echo $b->f2() . "<br/>";

输出:

Hello World
India
Hello World test
F1 Method Call
F2 Method Call

你不能通过子类对象调用父类受保护的方法,但你可以通过该对象在子类方法中调用。 echo $b->test2() . "
";
- Al-Amin

7
  • 抽象类只包含方法的声明,不能定义实现。
  • 使用关键字abstract来定义抽象类。
  • 抽象类不可能实现多重继承
  • PHP 5的最新版本引入了抽象类和方法。
  • 定义为抽象的类无法创建对象(不能被实例化)。

0

抽象类就像普通类一样,它包含变量、保护变量函数和构造函数,唯一不同的是它包含抽象方法。

抽象方法指的是没有定义的空方法,因此抽象类的唯一区别在于我们无法创建抽象类的对象。

抽象类必须包含抽象方法,并且这些方法必须在其继承类中定义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接