我希望函数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");
}
答案 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