Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/253.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_Class_Oop_Restriction - Fatal编程技术网

Php 类限制:函数可见性

Php 类限制:函数可见性,php,class,oop,restriction,Php,Class,Oop,Restriction,我希望函数explicitSetX($value){}在特定任务中是公共的,否则它应该是私有的。(私人电脑的功能) (我对如何编写通用setter不感兴趣,这个 问题是关于可见性/可接受性) 如果要公开访问属性,为什么要将属性声明为私有?在任何情况下,都可以使用将数据写入私有/受保护变量 public function __set($name, $value){ $this->$name = $value; } 或者,您可以将值传递到构造函数中: public function

我希望函数explicitSetX($value){}在特定任务中是公共的,否则它应该是私有的。(私人电脑的功能)

(我对如何编写通用setter不感兴趣,这个 问题是关于可见性/可接受性)


如果要公开访问属性,为什么要将属性声明为私有?在任何情况下,都可以使用将数据写入私有/受保护变量

public function __set($name, $value){
    $this->$name = $value;
}
或者,您可以将值传递到构造函数中:

public function __construct($A, $B, $C){
    $this->A = $A;
    $this->B = $B;
    $this->C = $C;
}
您可以使用关联数组作为参数,而不是foreach循环:

public function __construct(array $args){
    foreach ($args as $key=>$value){
        $this->$key = $value;
    }
}

构造函数的签名可能应该是_构造(数组$args=null),因此您可以使用new Obj($args)和new Obj(),但如果$args不是空的,您必须在正文中进行检查。

这是哈基什式的,不推荐使用,但您可以这样做:

class My_Object{

    // Final will disallow ovverriding
    public final function genericArrSetter ( $property, $value ){

        // Get caller function name
        $callers = debug_backtrace();

        // If it's not myStart do something more or less nasty
        if($callers[1]['function'] !== 'myStart')
        {
            throw new Exception('This is not allowed');
        }
        $this->$property = $value;
    }
}
例如:

function myStart (){
// set all data in Obj via generic setter
$obj = new Obj();
$obj-> genericArrSetter("x","value for x");
}

function OtherStart (){
// set all data in Obj via explicit setter
$obj = new Obj();
$obj-> explicitSetX ("value for x");
// Below will throw exception
$obj-> genericArrSetter("x","value for x");
}
有关呼叫者名称的更健壮的解决方案,请参见:


免责声明:未测试不推荐

唯一可行的方法是使用接口和类型提示

声明两个接口:

interface ExplicitSetter {
    public function setExplicitX($value);
}

interface GenericSetter {
    public function setGeneric($x, $value);
}
您的类实现了这两者

class MyObject implements ExplicitSetter, GenericSetter {
    private $x;

    public function setExplicitX($value) {
        $this->x = $value;
    }

    public function setGeneric($x, $value) {
        $this->x = $value;
    }

    public function __toString() {
        return $this->x;
    }
}
现在,您可以使用类型暗示仅公开您感兴趣的接口。尝试使用接口未声明的方法将导致错误

function useExplicitSetter(ExplicitSetter $setter) {
    $setter->setExplicitX('Hello explicit');
}

function useGenericSetter(GenericSetter $setter) {
    $setter->setGeneric('x', 'Hello generic');
}
用法:

$obj = new MyObject();

useExplicitSetter($obj);
echo $obj; // Hello explicit

useGenericSetter($obj);
echo $obj; // Hello generic

首先:请使用
$
声明变量<代码>私人x不正确,请使用
private$x,,第二:函数
myStart
OtherStart
在类
Obj
?现在可能需要更容易理解。因此,您希望在
myStart
中使用
genericArrSetter
函数public,在
OtherStart
中使用private?我希望能够在一个函数I中使用genericArrSetter有。在所有其他情况下,GenericarSetter不应该被访问。这不是我的问题。那么也许你应该澄清一下。如果您想要一个可公开访问的泛型集函数,那么已经有一个内置函数,缺少的到底是什么?如果要将值硬编码到myStart中,为什么不将它们硬编码到类定义中?它们不是硬编码的。我不想把这个问题描述得一团糟,仅此而已。X和X的值是从文件中自动提取的。我更新了问题,现在想你有其他答案了吗?这将允许只从
myStart
调用
genericArrSetter
(或以任何方式命名)。如你在评论中所写。啊,是的,谢谢!虽然我认为会有一个更合适的OOP来处理这个问题。我考虑的一个解决方案是创建一个新类,该类继承对象并具有泛型setter。那么,至少它是分离的,并且更容易迫使其他开发人员使用正确的设置方式。好吧,作为一个好的实践类,应该不知道也不依赖于谁在调用它。很酷,我将阅读这篇文章。我想这就是我要找的!只有接口或抽象类才能完成您需要的任务。没有奇怪的魔术,只是简单的OOP。
$obj = new MyObject();

useExplicitSetter($obj);
echo $obj; // Hello explicit

useGenericSetter($obj);
echo $obj; // Hello generic