简体   繁体   中英

difference in C# and PHP OOP

I have a general OOP question.

If I have the following classes in C#

class Parent
{
    public string val = "Parent";

    public void getValue()
    {
        Console.WriteLine(this.val);
    }
}

class Child:Parent
{
    public string val = "Child";
}

Child child = new Child();
child.getValue();

The code outputs 'Parent'. As I understand it's because this points to Parent object, right?

If I do the same in PHP5:

class ParentClass {
public $val = 'parent';

    public function foo()
    {
        echo $this->val;
    }
}

class ChildClass extends ParentClass {
public $val = 'child';
}

$a = new ChildClass();
$a->foo();

The result will be 'child'.

Though if I change

public $val = 'parent'; 

to

private $val = 'parent';

then PHP will also show 'parent'. C# always return 'parent' with both public and private access modifiers.

Is there any reason for this? And which behavior is correct?

Any useful links to read will be highly appreciated!

Thank you!

There is no correct or incorrect behavior in your stated scenarios. The language designers did what made sense to them.

The reason you don't get the expected behavior in c# is because GetValue is being called in the Parent class, where "this" means the parent val.

To get the correct behavior, you would include the same method in the Child class, with the override keyword:

public class Child
{
    public string val = "Child";
    public override void GetValue()
    {
        Console.WriteLine(val);
    }
}

...which would print "Child" to the console.

I think PHP OOP is behaving this way because it does not use the override or virtual modifiers present in other OOP languages. My guess would be that is either a limitation on how PHP works, or it just took too much time to write something that could easily be avoided.

Here's how you would get similar results in C#:

class Parent
{
    // Public identifiers cannot be overridden in C#
    private string _val = "Parent";
    // Public properties can.
    public virtual string val
    {
        get { return _val; }
    }

    public void getValue()
    {
        Console.WriteLine(this.val);
    }
}

class Child : Parent
{
    private string _val = "Child";
    public virtual string val
    {
        get { return _val; }
    }
}

PHP's expression is not evaluated until runtime, so it makes sense for it to use the derived class's object. However, C#'s expression is evaluated at compile time. A base class function has no idea whether it will be overridden, so it will reference the string it knows about.

That's where the virtual keyword comes in for functions, which tell the compiler to expect this to be overridden. It will look up the function in the vtable. But there's no equivalent to that for data.

However, you could make it into a virtual property and you would have the behavior you expect. Since properties are functions in disguise, they use the vtable.

Here's the code to achieve the PHP effect.

class Parent{    
    public virtual string val 
    {
        get { return "Parent"; }
    }

    public void getValue()    
    {        
        Console.WriteLine(this.val);    
    }
}

class Child:Parent
{
    public override string val
    {
        get { return "Child"; }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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