разница в C # и PHP ООП - PullRequest
2 голосов
/ 27 июня 2009

У меня общий вопрос ООП.

Если у меня есть следующие классы в 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();

Код выводит «Родитель». Как я понимаю, это потому, что это указывает на родительский объект, верно?

Если я сделаю то же самое в PHP5:

class ParentClass {
public $val = 'parent';

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

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

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

Результатом будет 'child'.

Хотя, если я изменюсь

public $val = 'parent'; 

до

private $val = 'parent';

тогда PHP также покажет 'parent'. C # всегда возвращает 'parent' с модификаторами открытого и закрытого доступа.

Есть ли причина для этого? И какое поведение правильно?

Любые полезные ссылки для чтения будут высоко оценены!

Спасибо!

Ответы [ 3 ]

6 голосов
/ 27 июня 2009

В ваших заявленных сценариях нет правильного или неправильного поведения. Разработчики языка сделали то, что имело для них смысл.

Причина, по которой вы не получаете ожидаемого поведения в c #, заключается в том, что GetValue вызывается в классе Parent, где «this» означает родительский val.

Чтобы получить правильное поведение, вы должны включить тот же метод в класс Child с ключевым словом override:

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

... что выводит «Child» на консоль.

2 голосов
/ 27 июня 2009

Выражение PHP не вычисляется до времени выполнения, поэтому имеет смысл использовать объект производного класса. Однако выражение C # оценивается во время компиляции. Функция базового класса не знает, будет ли она переопределена, поэтому она будет ссылаться на строку, о которой она знает.

Вот здесь и используется виртуальное ключевое слово для функций, которые сообщают компилятору, что они должны быть переопределены. Он будет искать функцию в vtable. Но нет аналога для данных.

Тем не менее, вы можете превратить его в виртуальное свойство, и у вас будет поведение, которое вы ожидаете. Поскольку свойства являются скрытыми функциями, они используют vtable.

Вот код для достижения эффекта PHP.

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"; }
    }
}
2 голосов
/ 27 июня 2009

Я думаю, что PHP OOP ведет себя так, потому что он не использует переопределение или виртуальные модификаторы, присутствующие в других языках OOP. Я думаю, это либо ограничение на работу PHP, либо просто слишком много времени, чтобы написать что-то, чего можно легко избежать.

Вот как вы можете получить аналогичные результаты в 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; }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...