类限制:函数可见性

时间:2014-03-28 17:39:30

标签: php class oop restriction

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

(我对如何编写通用设置器不感兴趣,这个 问题是关于可见性/可访问性)

class My_Object{

public function genericArrSetter ( $property, $value ){

    $this->$property = $value;
}
}

class Obj extends My_Object{

private $x;
private $x1;
private $x2;
private $x3;
private $x4;
private $x5;
private $x6;
private $x7;
private $x8;

public function explicitSetX( $value){
    $this->XX = $value; 
}

}

/*
* Below functions run from outside
* I would like to force this behaviour since now
* its possible for others to use myStart. (way of setting)
*/

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

3 个答案:

答案 0 :(得分:1)

如果要公开访问属性,为什么要将属性声明为私有?无论如何,您可以使用magic method __set()将数据写入私有/受保护变量

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

构造函数的签名应该是__construct(array $ args = null)所以你可以使用新的Obj($ args)和新的Obj(),但如果$ args不是,你必须检查正文空。

答案 1 :(得分:0)

这很苛刻,不推荐,但你可以这样做:

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

有关来电者姓名的更强大的解决方案,请参阅:How to get name of calling function/method in PHP?

免责声明:未经测试不推荐

答案 2 :(得分:0)

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

声明两个接口:

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

http://sandbox.onlinephpfunctions.com/code/a7a7a4c4566b529762d4eea755c11a8a9a8734d4