3

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!

1
  • 1
    Note that C# will warn you about that code unless you use the 'new' keyword on the derived class's variable. Commented Jun 27, 2009 at 18:15

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

That being said, the PHP behavior seems more sensible...After all, that is what happens when you override a variable.
C# allows you to override variables it just requires that you mark them as overridable and explicitly specify that you want to override it. It gives the base class more control over the modifications that can be made to it.
2

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

4 Comments

This code doesn't compile. error CS0106: The modifier 'virtual' is not valid for this item
Yeah yeah. I forgot public identifiers cannot be overridden. Fixed.
Spencer, shouldn't it be override instead of virtual in the Child class?
@dasha, I should have explained that. For this example either one is fine. If you didn't want the Child.val property to be overridable then yes you would simply use the override keyword. The example I gave both allows the property to be overridden and overrides the property in the parent class.
2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.