在C#中获取和设置(私有)属性,而不使用getter setter魔术方法重载

问题描述 投票:5回答:4

摘要

代码示例:

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

    // other methods not shown for simplicity.
}

直接前进。让我假设$name是一个PRIVATE类成员(或属性,变量,字段,根据需要调用它)。有没有办法在PHP中执行这些操作:

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

没有使用__get($name)__set($name, $value)


背景

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

getName();
setName($value);

并不一定像这样的getter setter魔术方法重载:

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

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

有没有办法在不使用getter setter魔术方法重载的情况下在C#中获取和设置私有属性?


更新

为什么不是魔术方法?

  1. 网络上有传言说魔术方法比明确的getter setter方法快10倍,我还没有测试过,但要记住这是一件好事。 (想象它不是那么慢,只慢2倍,见下面的基准测试结果)
  2. 如果我使用魔术方法而不是将它们分成不同的函数,我必须在一个巨大的方法中填充所有内容,就像在显式getter setter中一样。 (此要求可能已由ircmaxell回答)

绩效高管基准测试

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

使用magic方法和method_exist:

(点击here查看代码)

  • 吸气成本为0.0004730224609375秒。
  • 二传手的成本为0.00014305114746094秒。

使用显式getter setter:

(点击here查看代码)

  • 吸气成本为0.00020718574523926秒。
  • Setter成本为7.9870223999023E-5秒(即0.00007xxx)。

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

php properties getter-setter setter getter
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';语法和私有/受保护的成员变量......


3
投票
ReflectionClass is your salvation

我知道Hendra为时已晚,但我相信它对其他许多人都有帮助。

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

在我看来,它是PHP中有史以来最好的类之一。

让我举个例子:

如果你有一个私有属性的对象,你想从外面修改它

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

使用方法eighter可以做同样的事情;

我希望我能帮忙;


2
投票

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

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

为了回应您提出的语言功能问题,我要说动态类型语言与静态类型语言不同。每个具有OOP的编程语言都有所不同:Object-Oriented Languages: A Comparison


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;
}
}
© www.soinside.com 2019 - 2024. All rights reserved.