Friday, December 10, 2010

Наследование классов (часть 2)

Итак, у нас два класса – Door и Window и базовый для них BaseObject (см часть 1). В базовом классе есть методы Open и Close.
class BaseObject
{
    private bool isOpened;
    public void Open()
    {
        isOpened = true;
    }
    public void Close()
    {
        isOpened = false;
    }
}

class Door : BaseObject
{
}

class Window : BaseObject
{
}

Мы знаем еще, что для Door при открытии и закрытии нужны дополнительные действия (т.е. методы) – открыть и закрыть дверь ключом (OpenByKey, CloseByKey). Добавить их не сложно:
class Door : BaseObject
{
    public void OpenByKey()
    {
    }
    public void CloseByKey()
    {
    }
}

Проблема будет в том, что при вызове метода Open нужно не забыть вызвать метод OpenByKey, иначе к нам заберутся воры J Ну а там где есть слово “нужно не забыть” – забудут наверняка, тем более, что не понятно, как подсказать программисту, использующему наш класс, что этот вызов вообще нужен.
Хорошо бы иметь свою реализацию метода Open, такую, что в ней уже вызывается работа с ключом. Получается, что с одной стороны, мы хотим использовать базовый класс и его реализацию, чтобы не дублировать код. С другой – иметь собственную реализацию этого метода.
Оказывается, сделать это очень легко – для этого используется перекрытие методов.
Метод в базовом классе мы должны обозначить как перекрываемый, добавив к нему слово virtual (метод будет называться виртуальным, но я пока не буду вдаваться в подробности почему):
class BaseObject
{
    private bool isOpened;
    public virtual void Open()
    {
        isOpened = true;
    }
    public virtual void Close()
    {
        isOpened = false;
    }
}

А в классе наследнике мы должны будем обозначить, что мы перекрываем метод базового класса. Для этого используется слово override:
class Door : BaseObject
{
    public override void Open()
    {
        base.Open();
        OpenByKey();
    }

    public override void Close()
    {
        base.Close();
        CloseByKey();
    }

    private void OpenByKey()
    {
    }
    private void CloseByKey()
    {
    }
}

Обратите внимание на две вещи. Во-первых, на вызов base.Open и base.Close в перекрытых методах. Это означает, что мы вызываем методы базового класса. И, во-вторых, методы работы с ключом я сразу же сделал закрытыми (private), т.к. больше нет необходимости вызывать их самостоятельно – все будет сделано внутри классов.

No comments: