简体   繁体   English

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

[英]Get and set (private) property in PHP as in C# without using getter setter magic method overloading

Summary 摘要

Code sample: 代码示例:

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

    // other methods not shown for simplicity.
}

Straight forward. 直接前进。 Let me assume that $name is a PRIVATE class member (or property, variable, field, call it as you wish) . 我假设$name是一个PRIVATE类成员(或属性,变量,字段,根据需要调用它) Is there any way to do these in PHP: 有没有办法在PHP中执行这些操作:

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

WITHOUT using __get($name) and __set($name, $value) . 没有使用__get($name)__set($name, $value)


Background 背景

I needed to check the assigned $value , therefore I simply need a getter setter like this: 我需要检查分配的$value ,因此我只需要一个这样的getter setter:

getName();
setName($value);

And NOT necessarily a getter setter magic method overloading like this: 并不一定像这样的getter setter魔术方法重载:

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

That said, I simply need a getter setter. 也就是说,我只需要一个吸气剂装置。 But that's NOT what I want. 但那不是我想要的。 It just doesn't feel like object oriented, for people from static typed language such as C++ or C# might feel the same way as I do. 它只是感觉不像面向对象,因为来自静态类型语言(如C ++或C#)的人可能会感觉和我一样。

Is there any way to get and set a private property in PHP as in C# without using getter setter magic method overloading? 有没有办法在不使用getter setter魔术方法重载的情况下在C#中获取和设置私有属性?


Update 更新

Why Not Magic Method? 为什么不是魔术方法?

  1. There are rumors floating around the web that magic method is 10x slower then explicit getter setter method, I haven't tested it yet, but it's a good thing to keep in mind. 网络上有传言说魔术方法比明确的getter setter方法快10倍,我还没有测试过,但要记住这是一件好事。 (Figured out that it's not that slow, just 2x slower, see the benchmark result below) (想象它不是那么慢,只慢2倍,见下面的基准测试结果)

  2. I have to stuff everything in one huge method if I use magic method rather then split them into different function for each property as in explicit getter setter. 如果我使用魔术方法而不是将它们分成不同的函数,我必须在一个巨大的方法中填充所有内容,就像在显式getter setter中一样。 (This requirement might have been answered by ircmaxell ) (此要求可能已由ircmaxell回答)

Performance Overhead Benchmarking 绩效高管基准测试

I'm curious about performance overhead between using magic method and explicit getter setter, therefore I created my own benchmark for both method and hopefully it can be useful to anyone read this. 我对使用魔术方法和显式getter setter之间的性能开销感到好奇,因此我为这两种方法创建了自己的基准测试,希望它对任何阅读此内容的人都有用。

With magic method and method_exist: 使用magic方法和method_exist:

(click here to see the code) (点击这里查看代码)

  • Getter costs 0.0004730224609375 second. 吸气成本为0.0004730224609375秒。
  • Setter costs 0.00014305114746094 second. 二传手的成本为0.00014305114746094秒。

With explicit getter setter: 使用显式getter setter:

(click here to see the code) (点击这里查看代码)

  • Getter costs 0.00020718574523926 second. 吸气成本为0.00020718574523926秒。
  • Setter costs 7.9870223999023E-5 second (that's 0.00007xxx). Setter成本为7.9870223999023E-5秒(即0.00007xxx)。

That said, both setter and getter with magic method and method exists justs costs 2x than the explicit getter setter. 也就是说,使用魔术方法和方法的setter和getter只需要比显式getter setter成本高2倍。 I think it's still acceptable to use it for a small and medium scale system. 我认为将它用于中小型系统仍然可以接受。

Nope. 不。

However what's wrong with using __get and __set that act as dynamic proxies to getName() and setName($val) respectively? 但是,使用__get__set作为getName()setName($val)动态代理有什么问题? Something like: 就像是:

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

That way you're not stuffing everything into one monster method, but you still can use $foo->bar = 'baz'; 那样你就不$foo->bar = 'baz';所有东西塞进一个怪物方法中,但是你仍然可以使用$foo->bar = 'baz'; syntax with private/protected member variables... 私有/受保护成员变量的语法...

ReflectionClass is your salvation

I know it's too late for Hendra but i'm sure it will be helpfull for many others. 我知道Hendra为时已晚,但我相信这对其他人来说会有所帮助。

In PHP core we have a class named ReflectionClass wich can manipulate everything in an object scope including visibility of properties and methods. 在PHP核心中,我们有一个名为ReflectionClass的类,它可以操作对象范围内的所有内容,包括属性和方法的可见性。

It is in my opinion one of the best classes ever in PHP. 在我看来,它是PHP中有史以来最好的类之一。

Let me show an example: 让我举个例子:

If you have an object with a private property and u want to modify it from outside 如果你有一个私有属性的对象,你想从外面修改它

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

This same thing you can do with methods eighter; 使用方法eighter可以做同样的事情;

I hope i could help; 我希望我能帮忙;

If using magical properties doesn't seem right then, as already pointed out by other posters, you can also consider ReflectionClass::getProperty and ReflectionProperty::setAccessible . 如果使用魔法属性似乎不正确,正如其他海报已经指出的那样,你也可以考虑ReflectionClass :: getPropertyReflectionProperty :: setAccessible

Or implement the necessary getter and setter methods on the class itself. 或者在类本身上实现必要的getter和setter方法。

In response to the language features issue that you raised, I'd say that having a dynamically typed language differ from a statically typed one is expected. 为了回应您提出的语言功能问题,我要说动态类型语言与静态类型语言不同。 Every programming language that has OOP implements it somewhat differently: Object-Oriented Languages: A Comparison . 每种具有OOP的编程语言都以不同的方式实现它: 面向对象的语言:比较

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM