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

How to declare abstract method in non-abstract class in PHP?

1
2
3
class absclass {
    abstract public function fuc();
}

报告:

PHP Fatal error: Class absclass
contains 1 abstract method and must
therefore be declared abstract or
implement the remaining methods
(absclass::fuc)

我想知道实现剩余方法意味着什么,如何实现?


参见PHP手册中有关类抽象的章节:

PHP 5 introduces abstract classes and methods. Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method's signature - they cannot define the implementation.

这意味着你要么必须

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

1
2
3
4
5
class absclass {
    public function fuc() { // implement the method body
        // which means it won't be abstract anymore
    };
}


我假定剩余的方法实际上是指您试图定义的抽象方法(在本例中是fuc()),因为可能存在的非抽象方法无论如何都是可以的。这可能是一个错误消息,可以使用更好的措辞:在它说"保留"的地方,应该说"抽象"。

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

1
abstract public function fuc();

…正确实施:

1
2
3
public function fuc(){
    // Code comes here
}

…或者,根据您的需要,将整个类抽象化:

1
2
3
abstract class absclass {
    abstract public function fuc();
}


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

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

不能重写常规方法并使其成为抽象方法,但必须(最终)重写所有抽象方法并使其成为非抽象方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?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 Fatal error: Class BadDog
contains 1 abstract method and must
therefore be declared abstract or
implement the remaining methods
(Dog::bark)

如果注释掉baddog类,则输出为:

1
2
3
name: Fred
gender: female
bowowwaoar

如果您试图直接实例化一只狗或一只passthebuckdog,如下所示:

1
2
$wrong = new Dog('somma','it');
$bad = new PassTheBuckDog('phamous','monster');

…它的炸弹有:

PHP Fatal error: Cannot instantiate
abstract class Dog

或者(如果你的评论是错的)

PHP Fatal error: Cannot instantiate
abstract class PassTheBuckDog

但是,您可以调用抽象类的静态函数:

1
2
3
4
5
6
7
8
9
10
11
12
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();

那就行了。


抽象关键字用于将类或方法标记为模式。它类似于接口,但可以包含变量和方法的实现。

关于抽象类有很多误解。下面是一个抽象狗类的例子。如果一个开发人员想要为其他开发人员或者自己创建一些基本的dog类来扩展,他就声明这个类是抽象的。您不能直接实例化dog类(没有人可以),但您可以通过自己的类扩展dog。聪明的狗伸出狗等。

Dog类声明为抽象的所有方法必须在扩展Dog的每个类中手动实现。

例如,抽象类dog有一个抽象方法dog::bark()。但所有的狗叫声都不一样。因此,在每个dog子类中,您必须描述狗是如何具体地吠叫的,所以您必须定义例如smartdog::bark()。


你被这个错误信息稍微误导了。在这种情况下,由于fuc是在这个类中定义的,所以在这个类中实现它是没有意义的。错误试图告诉您的是,非抽象类不能有抽象方法。一旦将抽象方法放入类的定义中,还必须将类本身标记为抽象。


这意味着抽象类的主体至少有一个抽象方法。所以类要么实现方法(非抽象的),要么声明为抽象的。


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

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

或者,在实际操作中(在命令行php-f"abstractu methodu normalu classu test.php"上的文件中测试):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
    class dad {
        function dad() {
            if (get_parent_class($this) !== false) {
                // implements some logic
                echo"I'm" , get_class($this) ,"
"
;
            } else {
                echo"I'm" , get_class($this) ,"
"
;
            }
        }
    }

    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()文档