Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
几乎是PHP中的最终方法?_Php_Inheritance_Overriding_Final - Fatal编程技术网

几乎是PHP中的最终方法?

几乎是PHP中的最终方法?,php,inheritance,overriding,final,Php,Inheritance,Overriding,Final,我在继承链中有两个抽象类,它们最终将成为一个泛型库: abstract class Foo { public function baz() { echo 'Foo::baz()'; } // other methods here } abstract class Bar extends Foo { public function baz() { echo 'Bar::baz()'; } } 这两个类是由开发人员扩展的,

我在继承链中有两个抽象类,它们最终将成为一个泛型库:

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
没有问题;但是,如果我将
Foo::baz()
设置为final
,那么
栏本身显然也无法覆盖它

PHP5.4的
trait
s可能会提供一个实用的解决方案,但我不能因此放弃对PHP5.4的支持。我最后的办法是保持原样,并使用文档来警告开发人员不要重写此方法,但如果可能的话,我希望找到更具体的方法


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

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

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

但是,您正在
Bar
中覆盖
Foo:baz()
。因此,这里的设计/需求存在一些基本问题。

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

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

这似乎是一种“思想”适用的情况。它有点重复,但它不涉及实现的重复,并为您提供所需的功能

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的最终版本。我不确定您是否喜欢包含或省略接口。。。PHP没有类型化变量,因此除了使用两个实现类强制执行契约之外,可能没有必要使用它。定义接口的缺点是其他人可以实现接口(尽管trait也是如此)


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

如果
Bar
需要覆盖
baz
,那么
Foo::baz
实际上并不包含“严格的RFC兼容代码”。如果有一个类需要覆盖它以使其真正兼容,你怎么知道没有其他人会有另一个类需要重写它,使它真正兼容其他东西?我不理解你的问题。您要么希望能够覆盖它,要么希望阻止它。但你必须做出决定。我可以问一下你想要什么吗?如果您想要两个不同的东西,那么您很可能没有相同的类型,因此不应该让这些类彼此扩展。也许你只想让两个类共享同一个接口或类似的东西?@hakra:这两个类共享所有其他方法的实现。让它们共享同一个接口是可以的,但是我必须复制共享的代码(但这将允许我更改
baz()
方法,并使它们都
final
)。@RobKennedy:RFC在两种不同的场景下定义了两种不同的行为。这些类中的每一个都为其中一个场景建模,但它们都共享许多其他代码。如果我不使用继承,那么我必须重复共享代码,在库的生命周期中保持同步,等等。我宁愿使用干代码而不是
final
方法,但我想在社区中寻找我忽略的替代方法(如果有的话)。请阅读整个问题。特别是,我已经说过这里存在设计/需求问题,我正在寻求满足我的两个标准的替代方案。重申我已经知道的不起作用的东西并不能回答我的问题。如果你确实特别指出,我看不到它,伙计:)如果你确实想要一些东西来回答你的问题,那么这里就是:
有没有其他设计可以用来强制这两种方法都不应该被覆盖?
回答:没有,这既不是我问的问题,也不是你自己问题的正确答案。:-)
我是否可以使用其他设计来强制这两种方法都不应被重写,同时保持代码干燥(例如,不删除继承并复制所有代码)?
这不是你问题的最后一句话所说的,还是我正在读隐形墨水?:p确实如此,但这不是您以前发布的内容。:-)不过,为了解决您的另一个问题,我确实声明我完全了解这里的冲突要求:
如果我将Foo::baz()设为final,那么Bar本身显然也无法覆盖它。
我猜您错过了这一部分。正如我在其他评论中所说,我特别寻找设计变通方法(比如我可以用PHP5.4的
trait
s做什么,只需要不满足>=5.4的要求)。我不是在问是否可以只为一个子类重写
final
方法,因为我知道这是不可能的。+1因为我从未想过这样做。不幸的是,我不能接受,因为\uu call()
将所有调用传递给
父级
来重新定义接口。谢谢你!