5

我在继承链中有两个抽象类,最终将成为一个通用库:

abstract class Foo {
    public function baz() {
        echo 'Foo::baz()';
    }

    // other methods here
}

abstract class Bar extends Foo {
    public function baz() {
        echo 'Bar::baz()';
    }
}

这两个类是由开发人员扩展的,我的问题是我想使它的baz()方法的实现都不能被覆盖(因为它们包含严格的符合 RFC 的代码)。制作Bar::baz() final没问题;但是,如果我 make Foo::baz() final,那么Bar它本身显然也不能覆盖它。

PHP 5.4trait可能会提供一个实用的解决方案,但我不能就此放弃对 PHP < 5.4 的支持。我最后的手段是保持原样并使用文档来警告开发人员不要覆盖此方法,但如果可能的话,我想找到更具体的东西。

是否有任何其他设计可以用来强制不应该重写这两种方法,同时保持代码干燥(例如,不删除继承和复制所有代码)?

4

3 回答 3

2

我想我有办法做到这一点。这更像是一个技巧,而不是一个真正干净的设计,但我想我明白了。

abstract class Foo {
private $bazBehaviour;
    public function __construct($bazBehaviour){
        $this->bazBehaviour=!empty($bazBehaviour)?$bazBehaviour:"defaultBazBehaviour";
    }
   final public function baz() {
       $this->bazBehaviour();
   }
   final protected function defaultBazBehaviour(){
        echo "Foo::Baz()";
    }
   // other methods here
}

abstract class Bar extends Foo {
    public function __construct(){
       parent::__construct("bazBehaviour");
    }
    final protected function bazBehaviour() {
        echo 'Bar::baz()';
     } 
}
class toto extends Bar{
     public function __construct(){
       parent::__construct();
    }
}
$d = new toto();
$d->baz();

使用 PHP 5.3.13 它发送: Bar::Baz()

于 2012-08-17T06:52:50.547 回答
1

这似乎是“优先组合优于继承”的想法适用的情况。它有点重复,但它不涉及重复实现并为您提供所需的功能。

interface Bazr {
    public function baz();

    public function myOtherMethod1();
    public function myOtherMethod2();
}

public class Foo implements Bazr {
  public final function baz() {} 
  public function myOtherMethod1() {/* default implementation of some method */}
  public function myOtherMethod2() {/* yeah */}
}

public class Bar implements Bazr {
  private parentBazr = null;
  public function __construct() {
    $this->parentBazr = new Foo();
  }

  public final function baz() {}
  public function myOtherMethod1() {
    $this->parentBazr->myOtherMethod1();
  }
  public function myOtherMethod2() {
    $this->parentBazr->myOtherMethod1();
  }
}

Foo 和 Bar 都可以扩展,Bar “组合” Foo 的功能,baz 在 Foo 和 Bar 中都是 final 的。我不确定您是否喜欢包含或省略接口... PHP 没有类型变量,因此除了与两个实现类强制执行合同之外,它可能没有必要。定义接口的缺点是其他人可以实现该接口(尽管对于 trait 也是如此)。

抱歉,如果我混合了 java/php 语法,我想我遗漏了一些“$”。

于 2012-08-17T08:12:13.200 回答
0

很抱歉,您的要求是矛盾的:

my problem is that I'd like to make it so that neither implementation of 
the baz() method can be overridden

但是,您在..so中是压倒一切的,这里的设计/要求存在一些基本问题。Foo:baz()Bar

于 2012-08-16T18:06:30.023 回答