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

use*_*729 54 php abstract-function

class absclass {
    abstract public function fuc();
}
Run Code Online (Sandbox Code Playgroud)

报告:

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

我想知道实现其余方法意味着什么,怎么做?

Gor*_*don 78

请参阅PHP手册中的"类提取 "一章:

PHP 5引入了抽象类和方法.定义为抽象的类可能无法实例化,并且包含至少一个抽象方法的任何类也必须是抽象的.定义为抽象的方法只是声明方法的签名 - 它们无法定义实现.

这意味着你要么必须这样做

abstract class absclass { // mark the entire class as abstract
    abstract public function fuc();
}
Run Code Online (Sandbox Code Playgroud)

要么

class absclass {
    public function fuc() { // implement the method body
        // which means it won't be abstract anymore
    };
}
Run Code Online (Sandbox Code Playgroud)

  • “任何包含至少一个抽象方法的类也必须是抽象的”是 PHP 特有的还是在 OO 语言中相当普遍? (2认同)

Álv*_*lez 31

我假设剩下的方法实际上是指您尝试定义的抽象方法(在本例中fuc()),因为可能存在的非抽象方法无论如何都是可以的.这可能是可以使用更好的措辞的错误消息:在那里说剩下的,应该说抽象.

修复非常简单(错误消息的一部分很好):您需要更改此:

abstract public function fuc();
Run Code Online (Sandbox Code Playgroud)

...进入适当的实施:

public function fuc(){
    // Code comes here
}
Run Code Online (Sandbox Code Playgroud)

...或者,根据您的需要,使整个班级变得抽象:

abstract class absclass {
    abstract public function fuc();
}
Run Code Online (Sandbox Code Playgroud)

  • 这怎么可能是答案?在这种情况下,"剩余方法"是指"fuc",正如错误消息所示,因为您已经将其声明为抽象但未声明类本身是抽象的.错误消息似乎完全措辞. (24认同)
  • @RobertGrant - 如果信息措辞完美,那么首先不会问这个问题. (4认同)
  • 呵呵......错误信息_is_凌乱,正如上面罗伯特的推理(因为"剩下的方法"在这种情况下指的是"fuc"'就是为什么错误的msg.令人困惑的原因......),但他仍然是正确的:接受的答案似乎没有回答这个问题.:)这是一个很好的"循环误解"案例,其中虚假的答案不是解决伪造的问题([见这里为什么](http://stackoverflow.com/questions/2558559/what-is-abstract-class-in- php))问题,但是提问者确实存在的实际问题,可能是错误地表达了?) (2认同)

Sha*_*ais 26

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

如果扩展抽象类,则必须实现其所有抽象函数,或者使子类抽象化.

您不能覆盖常规方法并使其成为抽象方法,但您必须(最终)覆盖所有抽象方法并使它们成为非抽象方法.

<?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();

?>
Run Code Online (Sandbox Code Playgroud)

该程序炸弹:

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

如果你注释掉BadDog类,那么输出是:

name: Fred
gender: female
bowowwaoar
Run Code Online (Sandbox Code Playgroud)

如果您尝试直接实例化Dog或PassTheBuckDog,如下所示:

$wrong = new Dog('somma','it');
$bad = new PassTheBuckDog('phamous','monster');
Run Code Online (Sandbox Code Playgroud)

..炸弹:

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

或者(如果你注释掉$错误的行)

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();
Run Code Online (Sandbox Code Playgroud)

这很好用.