Should I use C#-like property handling in PHP?

2019-07-15 06:34发布

问题:

Hey SO community, I saw here: http://www.mustap.com/phpzone_post_203_setter-and-getter an argument for using a type of property handling common to C#, that is: If in C#, you can define a class like this:

public class Person 
{
    private string _name;
    public string Name
    {
        get{ return _name; }
        set{ _name = value; }
    }
}

then why is it wise or not to define a similar property in php like this:

public class Person
{
    private var $name;    

    public function Name() 
    {
        if(func_num_args() == 0) {    return $this->name;  } 
        else {$this->name = func_get_arg(0);  }
    }
}

回答1:

IMO, that doesn't look clean in PHP. It's like you're trying to jam the C# way into PHP because you think it's a nice feature of C#.

I see it as: In PHP, you're making a single function for doing two completely different things, which doesn't make sense. Meanwhile, in C#, it is single property, which is designed to be a single point of access for an object to be set/retrieved.



回答2:

You're violating the Single Responsibility Principle by having one function be both a getter and a setter.

In c# it's just syntactic sugar, and is converted into a getter and setter, just like you should write it in php.

In fact, in c#, you can simplify it further by writing

public string Name { get; set; }

And the compiler will generate a private backing field, and your getter and setter functions for you.



回答3:

If you need to do some additional checking of the value to be set you may want to either define getFoo and setFoo methods or even better use property overloading. The latter will give the user the feeling of native property getting/setting. (The latter is what you do in C#. Only that there is only one method per class, not many.)



回答4:

it is wise, for example:

class Settings
{
    private $data = array();

    public function __call($key,$arguments = array())
    {
        return !count($arguments)) ? $this->data[$key] : $this->data[$key] = $arguments[0];
    }
}

Then doing

$Settings = new Settings();
$Settings->name('hello');
$Settings->foo('bar');

This now has created a unlimited amount of anonymous functions ready to use, this would usually be constructed using 2 methods, __get and __set this way you can define separation for methods and variables, example follows

class Settings
{
    private $data = array();

    public function __set($key,$val)
    {
        $this->data[$key] = $val;
    }
    public function __get($key)
    {
        return $this->data[$key];
    }
}

This would then allow you to set variables like so:

$Settings->foo = 'bar';

But you can go a little further then that and create a variable registry system:

so basically you can change the above class from Settings to VariableStorage and do the following:

class User extends VariableStorage{}
class Profile extends VariableStorage{}

And use like so:

$Profile = new Profile('Robert','Pitt',USER_PRIV_ADMIN);
$Profile->id = 56;
$Profile->userdata = $Database->GetUserData($Profile); //Reads $Profile->id

So that you only have to define the methods once and as long as you build your inherit structure to a good design it can work extremely well.



回答5:

Personally I use a similar pattern in my PHP. I think it is clean and fairly useful.

private $name;
public function name($name = null)
{
    if ($name === null) return $this->name;
    $this->name = $name;
}

You can even do this to enforce some type safety:

private $name;
public function name(string $name = null)
{
    if ($name === null) return $this->name;
    $this->name = $name;
}

You can also enforce setting/getting of a reference instead of a copy:

private $name;
public function &name(string &$name = null)
{
    if ($name === null) return $this->name;
    $this->name = &$name;
}

This is completely valid PHP and mimics C# quite nicely.

Also, the Single Responsibility Principle states:

The single responsibility principle is a computer programming principle that states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.

So, this does not break the Single Responsibility Principle as this is simply a class method used to get/set a class member variable.

The only down side here is that, on the instance of your class you'd have to call functions to get/set member variables instead of true properties. You could mix this design pattern with PHP's __get and __set, but that would just be more overhead.



标签: c# php oop