PHP 中的抽象类是什么?

发布于 2024-08-27 11:55:56 字数 34 浏览 8 评论 0原文

PHP 中的抽象类是什么?

如何使用?

What is an abstract class in PHP?

How can it be used?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

咿呀咿呀哟 2024-09-03 11:55:56

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

这样做的目的是提供一种模板来继承并强制继承类实现抽象方法。

因此,抽象类介于常规类和纯接口之间。此外,接口是抽象类的一种特殊情况,其中所有方法都是抽象的。

请参阅 PHP 手册的本节以获取更多参考。

An abstract class is a class that contains at least one abstract method, which is a method without any actual code in it, just the name and the parameters, and that has been marked as "abstract".

The purpose of this is to provide a kind of template to inherit from and to force the inheriting class to implement the abstract methods.

An abstract class thus is something between a regular class and a pure interface. Also interfaces are a special case of abstract classes where ALL methods are abstract.

See this section of the PHP manual for further reference.

放肆 2024-09-03 11:55:56

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

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.相同(或较少限制)的可见性:从抽象类继承时,父类声明中标记为抽象的所有方法都必须由子类定义;此外,这些方法必须以相同(或较少限制)的可见性来定义。例如,如果抽象方法定义为 protected,则函数实现必须定义为 protected 或 public,但不能定义为 private。

请注意,抽象方法不应该是私有的。

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

注意:请注意代码中类的顺序或位置可能会影响解释器并可能导致致命错误。
因此,当使用多个抽象级别时,请注意类在源代码中的定位。

下面的示例将导致致命错误:找不到“马”类

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

Abstract classes are classes that contain one or more abstract methods. An abstract method is a method that is declared, but contains no implementation. Abstract classes may not be instantiated, and require subclasses to provide implementations for the abstract methods.

1. Can not instantiate abstract class: Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract.

Example below :

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. Any class that contains at least one abstract method must also be abstract: Abstract class can have abstract and non-abstract methods, but it must contain at least one abstract method. If a class has at least one abstract method, then the class must be declared abstract.

Note: Traits support the use of abstract methods in order to impose requirements upon the exhibiting class.

Example below :

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. An abstract method can not contain body: Methods defined as abstract simply declare the method's signature - they cannot define the implementation. But a non-abstract method can define the implementation.

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. When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child :If you inherit an abstract class you have to provide implementations to all the abstract methods in it.

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. Same (or a less restricted) visibility:When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or a less restricted) visibility. For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public, but not private.

Note that abstract method should not be private.

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. Signatures of the abstract methods must match:When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child;the signatures of the methods must match, i.e. the type hints and the number of required arguments must be the same. For example, if the child class defines an optional argument, where the abstract method's signature does not, there is no conflict in the signature.

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. Abstract class doesn't support multiple inheritance:Abstract class can extends another abstract class,Abstract class can provide the implementation of interface.But it doesn't support multiple inheritance.

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

Note: Please note order or positioning of the classes in your code can affect the interpreter and can cause a Fatal error.
So, when using multiple levels of abstraction, be careful of the positioning of the classes within the source code.

below example will cause Fatal error: Class 'horse' not found

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());
旧瑾黎汐 2024-09-03 11:55:56

抽象类是这样的类
仅部分实施
程序员。它可能包含一个或多个
抽象方法。抽象方法
只是一个函数定义
用于告诉程序员
方法必须在孩子身上实施
类。

对此有很好的解释此处

An abstract class is a class that is
only partially implemented by the
programmer. It may contain one or more
abstract methods. An abstract method
is simply a function definition that
serves to tell the programmer that the
method must be implemented in a child
class.

There is good explanation of that here.

歌入人心 2024-09-03 11:55:56

抽象类
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

Abstract Class
1. Contains an abstract method
2. Cannot be directly initialized
3. Cannot create an object of abstract class
4. Only used for inheritance purposes

Abstract Method
1. Cannot contain a body
2. Cannot be defined as private
3. Child classes must define the methods declared in abstract class

Example Code:

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/>";

Output:

Hello World
India
Hello World test
F1 Method Call
F2 Method Call
在巴黎塔顶看东京樱花 2024-09-03 11:55:56
  • 抽象类只包含声明方法的签名,不能定义实现。
  • 抽象类是使用关键字 abstract 定义的。
  • 抽象类不可能实现多重继承
  • 最新版本的 PHP 5 引入了抽象类和方法。
  • 类定义为抽象,我们无法创建对象(可能无法实例化)
  • Abstract Class contains only declare the method's signature, they can't define the implementation.
  • Abstraction class are defined using the keyword abstract .
  • Abstract Class is not possible to implement multiple inheritance.
  • Latest version of PHP 5 has introduces abstract classes and methods.
  • Classes defined as abstract , we are unable to create the object ( may not instantiated )
柠檬色的秋千 2024-09-03 11:55:56

抽象类就像普通类一样,它包含变量,它包含受保护的变量,它包含构造函数,只有一件事不同,它包含抽象方法。

抽象方法是指没有定义的空方法,因此与抽象类的唯一区别是我们不能创建抽象类的对象

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

An abstract class is like the normal class it contains variables it contains protected variables functions it contains constructor only one thing is different it contains abstract method.

The abstract method means an empty method without definition so only one difference in abstract class we can not create an object of abstract class

Abstract must contains the abstract method and those methods must be defined in its inheriting class.

苄①跕圉湢 2024-09-03 11:55:56

它涉及“合同协议”,但也涉及责任分配。如果您确实分配了任务,这一点就会变得很明显。

长期以来,我一直在努力理解抽象类,因为经常与解释一起发布的示例并没有充分说明抽象的必要性。但今天我有一个有用的用例,可能对阅读本文的人有所帮助:

abstract class BaseFilter {
    const DEFAULT_SORT = NULL;

    protected int $sort;

    abstract protected function isValid( int $sort );


    public function getSort(): int { 
        
        return $this->sort;
    }

    public function setSort( int $sort ) {
        
        if (!$this->isValid($sort)) {
            $sort = static::DEFAULT_SORT;
        }

        $this->sort = $sort;
    }
}


class ProductFilter {
    const DEFAULT_SORT = 0;

    const SORT_NAME = 0;
    const SORT_CREATED_DATE = 1;

    const SORTS = [
        self::SORT_NAME,
        self::SORT_CREATED_DATE,
    ];


    protected function isValid( int $sort ) {

        return in_array($sort, self::SORTS, TRUE) === TRUE;
    }
}
  • “仅接受有效”的逻辑位于 BaseFilter 设置器中。
  • 扩展过滤器类没有任何 getter/setter(除了从 BaseFilter 继承的那些)——这使得该类中的代码更短(作为额外的好处)。
  • 什么构成有效可能取决于多种因素,即具有过滤逻辑的应用程序的不同形式中的不同排序类别;登录用户或用户权限。 BaseFilter 设置器不关心这些细节……或者它可能无法知道。它只想知道该值是否有效。

It's about "contract agreements" – but also about a distribution of responsibilities. This becomes apparent if you actually do distribute the tasks.

I had long struggled to comprehend abstract classes because the examples often posted with the explanations didn't illustrate enough the necessity for abstraction. But today I've had a useful use case which might be helpful for whoever reads this:

abstract class BaseFilter {
    const DEFAULT_SORT = NULL;

    protected int $sort;

    abstract protected function isValid( int $sort );


    public function getSort(): int { 
        
        return $this->sort;
    }

    public function setSort( int $sort ) {
        
        if (!$this->isValid($sort)) {
            $sort = static::DEFAULT_SORT;
        }

        $this->sort = $sort;
    }
}


class ProductFilter {
    const DEFAULT_SORT = 0;

    const SORT_NAME = 0;
    const SORT_CREATED_DATE = 1;

    const SORTS = [
        self::SORT_NAME,
        self::SORT_CREATED_DATE,
    ];


    protected function isValid( int $sort ) {

        return in_array($sort, self::SORTS, TRUE) === TRUE;
    }
}
  • The logic to "only accept if valid" is in the BaseFilter setter.
  • The extending filter class does not have any getters / setters (other than those inherited from the BaseFilter) – which makes for shorter code in that class (as a bonus plus).
  • What constitutes as valid may depend on various things, i.e. different sorting categories in different forms of your app that have a filter logic; logged-in user or user privileges. The BaseFilter setter does not care about those details … or it may not be able to know. All it wants to know is whether the value is valid.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文