取消定义方法或替代方法
Undefining a method or alternative
有了这个插件系统,就有一个Utility和一个Driver。驱动程序扩展了实用程序,但是,一些驱动程序支持与其他驱动程序不同的功能,一些不支持某些功能。
我的 class 会是这样的:
Class Utility {
public function MethodOne() {
# default MethodOne
}
public function MethodTwo() {
# default MethodTwo
}
}
class Driver extends Utility {
# MethodTwo not supported in this driver
}
取消定义方法的简单之处在于它允许开发人员使用 class 到 运行 调用 method_exists 以查看驱动程序是否支持该方法。
是否可以取消定义扩展中的方法 class 或者是否有更好的选择?
您不能在 child 中取消定义 parent 函数,这不是使用继承的好方法。任何 child class 都应该能够使用所有 parent 功能。 (否则,为什么要扩展?)
另一种解决方案是在每个特定驱动程序中只定义您需要的功能,而实用程序只包含所有驱动程序都可以使用的通用功能(这是最简单的),然后是驱动程序内部的驱动程序特定功能。
Class Utility {
public function MethodOne() {
# default MethodOne
}
public function MethodTwo() {
# default MethodTwo
}
}
class Driver extends Utility {
public function MethodThree() {
}
}
class Driver2 extends Utility {
public function MethodFour() {
}
}
这表明 Driver 和 Driver2 具有彼此不同的实现功能,但仍然具有 Utility 中可用的方法。
最终的解决方案(如果你想强制函数在驱动程序中,否则会抛出错误)是实现多个接口,每个接口将一些函数捆绑在一起:
Class Utility {
public function MethodOne() {
print "MethodOne";
}
public function MethodTwo() {
print "MethodTwo";
}
}
interface inter1 {
public function MethodThree();
}
interface inter2 {
public function MethodFour();
}
class Driver extends Utility implements inter1 {
public function MethodThree(){
print "MethodThree";
}
}
class Driver2 extends Utility implements inter2 {
public function MethodFour() {
print "MethodFour";
}
}
两种方案实现的是一样的,但是Driver必须在接口方案中实现MethodThree:
$d = new Driver();
print "Methods for Driver:\n";
foreach (array("MethodOne","MethodTwo","MethodThree","MethodFour") as $k) {
$p = method_exists($d, $k) ? 'true' : 'false';
print "\t ".$k.": " . $p ."\n";
}
$d = new Driver2();
print "Methods for Driver2:\n";
foreach (array("MethodOne","MethodTwo","MethodThree","MethodFour") as $k) {
$p = method_exists($d, $k) ? 'true' : 'false';
print "\t ".$k.": " . $p ."\n";
}
输出:
Methods for Driver:
MethodOne: true
MethodTwo: true
MethodThree: true
MethodFour: false
Methods for Driver2:
MethodOne: true
MethodTwo: true
MethodThree: false
MethodFour: true
如果你想让Driver2有MethodThree,那么你会写:
class Driver2 extends Utility implements inter2, inter1 {
public function MethodFour() {
print "MethodFour";
}
public function MethodThree() {
}
}
这个怎么样:
<?php
class Utility{
//will hold unimplemented methods foor every child
protected $unimplementedMethods = array();
protected function f1(){
//debug
echo __FUNCTION__ . "\n";
}
protected function f2(){
//debug
echo __FUNCTION__ . "\n";
}
//intercept the functions
public function __call($name, $arguments)
{
if (method_exists($this,$name) && !in_array($name, $this->unimplementedMethods)){
echo "Calling method: '$name'\n";
$this->$name();
}
else{
//return error or throw exception
echo "Method: '$name' is not implemented for this driver\n";
}
}
}
//driver1
class Driver1 extends Utility{
//set your non-implemented methods
protected $unimplementedMethods = array ('f2');
}
//driver2
class Driver2 extends Utility{
//set your non-implemented methods
protected $unimplementedMethods = array ('f1');
}
//init
$d1 = new Driver1();
$d2 = new Driver2();
$d1->f1(); //the ok method
$d1->f2(); //the nok method
$d2->f1(); //the nok method
$d2->f2(); //the ok method
?>
输出:
Calling method: 'f1'
Method: 'f2' is not implemented for this driver
Method: 'f1' is not implemented for this driver
Calling method: 'f2'
在面向对象的语言中,您通常无法更改
一种方法,如果不是为了扩大它。
但是,虽然 PHP 不支持限制具有经典继承的方法的可见性,但事实证明它在涉及特征时允许它。
<?php
trait Utility {
public function methodOne() {
}
public function methodTwo() {
}
}
class Driver {
use Utility;
protected function methodTwo(){
}
}
我们开始吧:
php > $driver = new Driver;
php > $driver->methodTwo();
PHP Fatal error: Call to protected method Driver::methodTwo() from context '' in php shell code on line 1
警告:
method_exists
无论可见性如何,都将 return 为真。你必须使用 is_callable
:
php > var_dump(is_callable([$driver, 'methodOne']));
bool(true)
php > var_dump(is_callable([$driver, 'methodTwo']));
bool(false)
祝你项目顺利!
有了这个插件系统,就有一个Utility和一个Driver。驱动程序扩展了实用程序,但是,一些驱动程序支持与其他驱动程序不同的功能,一些不支持某些功能。
我的 class 会是这样的:
Class Utility {
public function MethodOne() {
# default MethodOne
}
public function MethodTwo() {
# default MethodTwo
}
}
class Driver extends Utility {
# MethodTwo not supported in this driver
}
取消定义方法的简单之处在于它允许开发人员使用 class 到 运行 调用 method_exists 以查看驱动程序是否支持该方法。
是否可以取消定义扩展中的方法 class 或者是否有更好的选择?
您不能在 child 中取消定义 parent 函数,这不是使用继承的好方法。任何 child class 都应该能够使用所有 parent 功能。 (否则,为什么要扩展?)
另一种解决方案是在每个特定驱动程序中只定义您需要的功能,而实用程序只包含所有驱动程序都可以使用的通用功能(这是最简单的),然后是驱动程序内部的驱动程序特定功能。
Class Utility {
public function MethodOne() {
# default MethodOne
}
public function MethodTwo() {
# default MethodTwo
}
}
class Driver extends Utility {
public function MethodThree() {
}
}
class Driver2 extends Utility {
public function MethodFour() {
}
}
这表明 Driver 和 Driver2 具有彼此不同的实现功能,但仍然具有 Utility 中可用的方法。
最终的解决方案(如果你想强制函数在驱动程序中,否则会抛出错误)是实现多个接口,每个接口将一些函数捆绑在一起:
Class Utility {
public function MethodOne() {
print "MethodOne";
}
public function MethodTwo() {
print "MethodTwo";
}
}
interface inter1 {
public function MethodThree();
}
interface inter2 {
public function MethodFour();
}
class Driver extends Utility implements inter1 {
public function MethodThree(){
print "MethodThree";
}
}
class Driver2 extends Utility implements inter2 {
public function MethodFour() {
print "MethodFour";
}
}
两种方案实现的是一样的,但是Driver必须在接口方案中实现MethodThree:
$d = new Driver();
print "Methods for Driver:\n";
foreach (array("MethodOne","MethodTwo","MethodThree","MethodFour") as $k) {
$p = method_exists($d, $k) ? 'true' : 'false';
print "\t ".$k.": " . $p ."\n";
}
$d = new Driver2();
print "Methods for Driver2:\n";
foreach (array("MethodOne","MethodTwo","MethodThree","MethodFour") as $k) {
$p = method_exists($d, $k) ? 'true' : 'false';
print "\t ".$k.": " . $p ."\n";
}
输出:
Methods for Driver:
MethodOne: true
MethodTwo: true
MethodThree: true
MethodFour: false
Methods for Driver2:
MethodOne: true
MethodTwo: true
MethodThree: false
MethodFour: true
如果你想让Driver2有MethodThree,那么你会写:
class Driver2 extends Utility implements inter2, inter1 {
public function MethodFour() {
print "MethodFour";
}
public function MethodThree() {
}
}
这个怎么样:
<?php
class Utility{
//will hold unimplemented methods foor every child
protected $unimplementedMethods = array();
protected function f1(){
//debug
echo __FUNCTION__ . "\n";
}
protected function f2(){
//debug
echo __FUNCTION__ . "\n";
}
//intercept the functions
public function __call($name, $arguments)
{
if (method_exists($this,$name) && !in_array($name, $this->unimplementedMethods)){
echo "Calling method: '$name'\n";
$this->$name();
}
else{
//return error or throw exception
echo "Method: '$name' is not implemented for this driver\n";
}
}
}
//driver1
class Driver1 extends Utility{
//set your non-implemented methods
protected $unimplementedMethods = array ('f2');
}
//driver2
class Driver2 extends Utility{
//set your non-implemented methods
protected $unimplementedMethods = array ('f1');
}
//init
$d1 = new Driver1();
$d2 = new Driver2();
$d1->f1(); //the ok method
$d1->f2(); //the nok method
$d2->f1(); //the nok method
$d2->f2(); //the ok method
?>
输出:
Calling method: 'f1'
Method: 'f2' is not implemented for this driver
Method: 'f1' is not implemented for this driver
Calling method: 'f2'
在面向对象的语言中,您通常无法更改 一种方法,如果不是为了扩大它。
但是,虽然 PHP 不支持限制具有经典继承的方法的可见性,但事实证明它在涉及特征时允许它。
<?php
trait Utility {
public function methodOne() {
}
public function methodTwo() {
}
}
class Driver {
use Utility;
protected function methodTwo(){
}
}
我们开始吧:
php > $driver = new Driver;
php > $driver->methodTwo();
PHP Fatal error: Call to protected method Driver::methodTwo() from context '' in php shell code on line 1
警告:
method_exists
无论可见性如何,都将 return 为真。你必须使用 is_callable
:
php > var_dump(is_callable([$driver, 'methodOne']));
bool(true)
php > var_dump(is_callable([$driver, 'methodTwo']));
bool(false)
祝你项目顺利!