7

概括

代码示例:

Class People {
    // private property.
    private $name;

    // other methods not shown for simplicity.
}

直线前进。让我假设它$namePRIVATE类成员(或属性、变量、字段,随意调用)。有没有办法在 PHP 中做到这些:

$someone = new People();
$someone->name = $value;
$somevar = $someone->name;

使用__get($name)and __set($name, $value)


背景

我需要检查assigned $value,因此我只需要一个像这样的getter setter:

getName();
setName($value);

而且不一定像这样重载getter setter魔术方法:

__get($value); 
__set($value, $name);

也就是说,我只需要一个吸气剂二传手。但这不是我想要的。它只是感觉不像是面向对象的,因为使用静态类型语言(如 C++ 或 C#)的人可能会有和我一样的感觉。

有什么方法可以像在 C# 中一样在 PHP 中获取和设置私有属性,而无需使用 getter setter 魔术方法重载?


更新

为什么不是魔术方法?

  1. 网上有传言说魔术方法比显式 getter setter 方法慢 10 倍,我还没有测试过,但要记住这是一件好事。(发现它并没有那么慢,只是慢了 2 倍,请参阅下面的基准测试结果)

  2. 如果我使用魔术方法而不是将它们拆分为每个属性的不同函数,就像在显式 getter setter 中那样,我必须将所有内容都填充到一个巨大的方法中。(此要求可能已由ircmaxell回答)

性能开销基准测试

我很好奇使用魔法方法和显式 getter setter 之间的性能开销,因此我为这两种方法创建了自己的基准,希望它对任何阅读本文的人都有用。

使用魔术方法和method_exist:

(点击这里查看代码)

  • 吸气剂花费 0.0004730224609375 秒。
  • Setter 花费 0.00014305114746094 秒。

使用显式 getter setter:

(点击这里查看代码)

  • 吸气剂花费 0.00020718574523926 秒。
  • Setter 花费 7.9870223999023E-5 秒(即 0.00007xxx)。

也就是说,具有魔术方法和方法的 setter 和 getter 的成本是显式 getter setter 的 2 倍。我认为将它用于中小型系统仍然可以接受。

4

4 回答 4

7

没有。

但是,使用__get和分别__set充当动态代理有getName()什么问题setName($val)?就像是:

public function __get($name) { 
    if (method_exists($this, 'get'.$name)) { 
        $method = 'get' . $name; 
        return $this->$method(); 
    } else { 
        throw new OutOfBoundsException('Member is not gettable');
    }
}

这样你就不会把所有东西都塞进一个怪物方法中,但你仍然可以使用$foo->bar = 'baz';带有私有/受保护成员变量的语法......

于 2011-02-07T19:18:55.373 回答
4
ReflectionClass is your salvation

我知道这对亨德拉来说太晚了,但我相信这对许多其他人会有帮助。

在 PHP 核心中,我们有一个名为 ReflectionClass 的类,它可以操作对象范围内的所有内容,包括属性和方法的可见性。

在我看来,这是 PHP 中最好的类之一。

让我举个例子:

如果您有一个具有私有属性的对象并且您想从外部修改它

$reflection = new ReflectionClass($objectOfYourClass);
$prop = $reflection->getProperty("PrivatePropertyName");
$prop->setAccessible(true);
$prop->setValue($objectOfYourClass, "SOME VALUE");
$varFoo = $prop->getValue();

你可以用方法八来做同样的事情;

我希望我能帮上忙;

于 2013-08-19T17:50:05.093 回答
2

如果使用魔法属性似乎不正确,正如其他海报已经指出的那样,您还可以考虑ReflectionClass::getPropertyReflectionProperty::setAccessible

或者在类本身上实现必要的 getter 和 setter 方法。

针对您提出的语言功能问题,我想说动态类型的语言与静态类型的语言不同。每种具有 OOP 的编程语言都以不同的方式实现它:面向对象的语言:比较

于 2011-02-07T19:10:57.837 回答
0
class conf_server
{

private $m_servidor="localhost";
private $m_usuario = "luis";
private $m_contrasena = "luis";
private $m_basededatos = "database";

public function getServer(){
    return $this->m_servidor;
}
public function setServer($server){
    $this->m_servidor=$server;
}
public function getUsuario(){
    return $this->m_usuario;
}
public function setUsuario($user){
    $this->m_usuario=$user;
}
public function getContrasena(){
    return $this->m_contrasena;
}
public function setContrasena($password){
    $this->m_contrasena=$password;
}
public function getBaseDatos(){
    return $this->m_basededatos;
}
public function setBaseDatos($database){
    $this->m_basededatos->$database;
}
}
于 2014-02-04T01:35:08.610 回答