如何在非抽象类中声明抽象方法 PHP?

61
class absclass {
    abstract public function fuc();
}

报告:

PHP致命错误: 类absclass包含1个抽象方法,因此必须声明为抽象类或实现其余方法(absclass::fuc)

我想知道实现其余方法是什么意思,怎样实现?

7个回答

82
请看PHP手册中有关类抽象的章节:

PHP 5引入了抽象类和方法。定义为抽象的类不能被实例化,而任何包含至少一个抽象方法的类也必须是抽象的。抽象方法仅声明方法的签名,它们不能定义实现。

这意味着您要么

abstract class absclass { // mark the entire class as abstract
    abstract public function fuc();
}

或者
class absclass {
    public function fuc() { // implement the method body
        // which means it won't be abstract anymore
    };
}

2
“任何包含至少一个抽象方法的类必须也是抽象的”这个规则是仅适用于PHP还是在面向对象语言中比较普遍的呢? - Caltor
例如在 F# 中也是一样的。 - broch
@Caltor,你的意思是“必须明确声明为抽象吗”?那么C#也是一个例子 - Sz.

37

我认为“剩余的方法”实际上是指您正在尝试定义的抽象方法(在本例中是 fuc()),因为可能存在的非抽象方法已经可以了。这可能是一条需要更精确措辞的错误消息:在它说“剩余”的地方,可以改为说“抽象的”。

修复也很简单(错误消息的这一部分是正确的):您需要将以下内容更改为:

abstract public function fuc();

将其转化为适当的实现:

public function fuc(){
    // Code comes here
}

或者,根据您的需求,也可以将整个类设为抽象类:

abstract class absclass {
    abstract public function fuc();
}

27
这怎么可能是答案?在这种情况下,“remaining methods”指的是“fuc”,就像错误信息所说的那样,因为你已经将其声明为抽象方法,但没有将类本身声明为抽象类。错误信息似乎表述得非常清楚。 - Rob Grant
7
如果这条信息措辞得完美无缺,那么这个问题就不会被提出来了。 - SDC
2
呵呵...错误信息确实很混乱,就像Robert的推理一样(因为“在这种情况下‘remaining methods’指的是‘fuc’”这个原因是导致错误信息令人困惑的根源...),但他毕竟是正确的:被接受的答案似乎并没有回答问题。 :) 这是一个很好的“循环误解”的例子吗?即虚假答案解决了不真实的问题(在这里看为什么),而不是解决了提问者实际上遇到的问题,可能是错误表达的问题? - Sz.

30

抽象类不能直接实例化,但可以包含抽象方法和非抽象方法。

如果你继承了一个抽象类,你必须要么实现所有它的抽象方法,要么将子类也声明为抽象类。

你不能覆盖一个普通的方法并将其变成抽象方法,但你必须(最终)覆盖所有抽象方法并将它们变成非抽象方法。

<?php

abstract class Dog {

    private $name = null;
    private $gender = null;

    public function __construct($name, $gender) {
        $this->name = $name;
        $this->gender = $gender;
    }

    public function getName() {return $this->name;}
    public function setName($name) {$this->name = $name;}
    public function getGender() {return $this->gender;}
    public function setGender($gender) {$this->gender = $gender;}

    abstract public function bark();

}

// non-abstract class inheritting from an abstract class - this one has to implement all inherited abstract methods.
class Daschund extends Dog {
    public function bark() {
        print "bowowwaoar" . PHP_EOL;
    }
}

// this class causes a compilation error, because it fails to implement bark().
class BadDog extends Dog {
    // boom!  where's bark() ?
}

// this one succeeds in compiling, 
// it's passing the buck of implementing it's inheritted abstract methods on to sub classes.
abstract class PassTheBuckDog extends Dog {
    // no boom. only non-abstract subclasses have to bark(). 
}

$dog = new Daschund('Fred', 'male');
$dog->setGender('female');

print "name: " . $dog->getName() . PHP_EOL;
print "gender: ". $dog->getGender() . PHP_EOL;

$dog->bark();

?>

那个程序崩溃了,错误信息如下:

PHP致命错误:类BadDog包含1个抽象方法, 必须声明为抽象或实现剩余的方法(Dog::bark)

如果您将BadDog类注释掉,则输出结果为:

name: Fred
gender: female
bowowwaoar
如果您尝试直接实例化狗或PassTheBuckDog,如下所示:
$wrong = new Dog('somma','it');
$bad = new PassTheBuckDog('phamous','monster');

执行时会报错:

PHP 致命错误:无法实例化抽象类 Dog

或者(如果将 $wrong 行注释掉)

PHP 致命错误:无法实例化抽象类 PassTheBuckDog

但是你可以调用一个抽象类的静态函数:

abstract class Dog {
    ..
    public static function getBarker($classname, $name, $gender) {
        return new $classname($name, $gender);
    }
    ..
}

..

$other_dog = Dog::getBarker('Daschund', 'Wilma', 'female');
$other_dog->bark();

那很好地解决了问题。


公共函数吠叫() - Raptor

4
抽象关键词用于将类或方法标记为模式。它类似于接口,但可以包含变量和方法的实现。
关于抽象类存在很多误解。以下是一个抽象的狗类的示例。如果开发人员想要创建一些基本的狗类供其他开发人员或自己扩展,他将该类声明为抽象类。您不能直接实例化Dog类(没有人能够),但是您可以通过自己的类来扩展Dog。例如SmartDog扩展Dog等。
由Dog类声明为抽象类的所有方法必须在每个扩展Dog的类中手动实现。
例如,抽象类Dog具有一个抽象方法Dog :: Bark()。但是所有的狗叫声都不同。因此,在每个Dog子类中,您必须具体描述该狗如何叫,因此您必须定义例如SmartDog :: Bark()。

4

这个错误信息有点误导。在这种情况下,由于在这个类中定义了fuc函数,因此将其实现到该类中并没有太多意义。错误信息试图告诉你的是:非抽象类不能有抽象方法。只要在类定义中放置了一个抽象方法,就必须将该类本身标记为抽象的。


3

这意味着抽象类至少有一个抽象方法。因此,您的类必须实现该方法(非抽象),或声明为抽象。


1

我想在一个非抽象类(普通类?)中使用一个抽象方法,发现可以使用get_parent_class()将方法的内容包装在一个'if'语句中,如下所示:

if (get_parent_class($this) !== false) {

或者,在实际应用中(在命令行上测试文件:php -f“abstract_method_normal_class_test.php”):

<?php
    class dad {
        function dad() {
            if (get_parent_class($this) !== false) {
                // implements some logic
                echo "I'm " , get_class($this) , "\n";
            } else {
                echo "I'm " , get_class($this) , "\n";
            }
        }
    }

    class child extends dad {
        function child() {
            parent::dad();
        }
    }

    $foo = new dad();
    $bar = new child();
?>

Output:
I'm dad
I'm child

PHP get_parent_class() 文档


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