【问题标题】:How to declare abstract method in non-abstract class in PHP?如何在 PHP 的非抽象类中声明抽象方法?
【发布时间】:2011-01-23 05:03:27
【问题描述】:
class absclass {
    abstract public function fuc();
}

报告:

PHP 致命错误:类 absclass 包含 1 个抽象方法并且必须 因此被宣布为抽象的或 实现剩下的方法 (absclass::fuc)

我想知道实现剩下的方法是什么意思,怎么做?

【问题讨论】:

    标签: php abstract-function


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      此错误消息使您误入歧途。在这种情况下,由于在 this class 中定义了 fuc,因此在此类中实现它实际上没有意义。错误试图告诉您的是非抽象类不能有抽象方法。一旦您将抽象方法放入类的定义中,您还必须将类本身标记为抽象。

      【讨论】:

        【解决方案3】:

        我认为 remaining methods 实际上是指您尝试定义的抽象方法(在本例中为fuc()),因为无论如何可能存在的非抽象方法都可以。这可能是一条错误消息,可以使用更精确的措辞:它说 remaining 的地方可能是 abstract

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

        abstract public function fuc();
        

        ...进入正确的实现:

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

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

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

        【讨论】:

        • 这怎么可能是答案?正如错误消息所说,在这种情况下,“剩余方法”指的是“fuc”,因为您已将其声明为抽象但未将类本身声明为抽象。错误消息似乎措辞完美。
        • @RobertGrant - 如果消息措辞完美,那么一开始就不会问这个问题。
        • 呵呵... 错误信息 is 乱七八糟,就像上面 Robert 的推理一样(因为在这种情况下,'"remaining methods" 是指 "fuc"' 是err. msg. 令人困惑的原因......),但他毕竟仍然是对的:接受的答案似乎没有回答这个问题。 :) 这是一个很好的“循环误解”案例,虚假的答案解决的不是虚假的 (see here why) 问题,而是提问者真正遇到的实际问题,大概是错误的表达?)
        【解决方案4】:

        Class Abstraction in the PHP manual的章节:

        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
            };
        }
        

        【讨论】:

        • “任何包含至少一个抽象方法的类也必须是抽象的”是 PHP 特有的还是在 OO 语言中相当普遍?
        • 这在 F# 中也是一样的
        • @Caltor,您的意思是“还必须明确声明抽象”?然后C# is an example也一样。
        【解决方案5】:

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

        如果你扩展一个抽象类,你必须要么实现它的所有抽象函数,要么让子类抽象。

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

        <?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 个抽象方法并且必须 因此被宣布为抽象的或 实现剩下的方法 (狗::吠声)

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

        name: Fred
        gender: female
        bowowwaoar
        

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

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

        ..it 炸弹:

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

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

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

        效果很好。

        【讨论】:

        • public public function bark() ?
        【解决方案6】:

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

        关于抽象类有很多误解。这是一个抽象 Dog 类的示例。如果开发人员想为其他开发人员或自己创建一些基本的 Dog 类来扩展,他将类声明为抽象类。您不能直接实例化 Dog 类(没有人可以),但您可以通过自己的类扩展 Dog。 SmartDog 扩展了 Dog 等。

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

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

        【讨论】:

          【解决方案7】:

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

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

          或者,在行动中(在 cmd 行的文件中测试: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() Documentation

          【讨论】:

            猜你喜欢
            • 2016-05-10
            • 1970-01-01
            • 1970-01-01
            • 2012-09-21
            • 2012-09-16
            • 2017-05-13
            • 1970-01-01
            • 2014-02-26
            • 2015-02-28
            相关资源
            最近更新 更多