Наследование класса C # - PullRequest
       25

Наследование класса C #

7 голосов
/ 22 февраля 2010

привет. у меня есть следующий класс:

public class Ship
{
    public enum ValidShips
    {
        Minesweeper,
        Cruiser,
        Destroyer,
        Submarine,
        AircraftCarrier
    }

    public enum ShipOrientation
    {
        North,
        East,
        South,
        West
    }

    public enum ShipStatus
    {
        Floating,
        Destroyed
    }

    public ValidShips shipType { get; set; }

    public ShipUnit[] shipUnit { get; set; }

    public ShipOrientation shipOrientation { get; set; }

    public ShipStatus shipStatus { get; set; }

    public Ship(ValidShips ShipType, int unitLength)
    {
        shipStatus = ShipStatus.Floating;

        shipType = ShipType;

        shipUnit = new ShipUnit[unitLength];

        for (int i = 0; i < unitLength; i++)
        {
            shipUnit[i] = new ShipUnit();
        }
    }
}

Я хотел бы унаследовать этот класс следующим образом:

public class ShipPlacementArray : Ship
{

}

это имеет смысл.

я хотел бы знать, как удалить некоторые функции базового класса?

например:

    public ShipUnit[] shipUnit { get; set; } // from base class

Мне бы хотелось, чтобы это было:

    public ShipUnit[][] shipUnit { get; set; } // in the derived class

У меня вопрос, как мне реализовать код, который полностью скрывает базовый класс shipUnit?

в противном случае я получу две реализации shipUnit в производном классе.

спасибо за ваше время.

ShipPlacementArray работает только с одним кораблем. но массив отражает направления, в которых можно разместить корабль.

Ответы [ 11 ]

15 голосов
/ 22 февраля 2010

я хотел бы знать, как удалить определенные функции базового класса?

Вы не делаете. Это не точка наследования. Смысл наследования заключается в наследовании функциональности базового класса - всех - и добавлении / изменении вещей. Это для отношений "есть", например, "автомобиль - это автомобиль".

Мой вопрос: как мне реализовать код, полностью скрывающий базовый класс shipUnit?

Звучит так, будто вы хотите, чтобы ShipPlacementArray был оболочкой или контейнером из нескольких Ship объектов. Это не похоже на случай, когда следует использовать наследование.

Задайте себе вопрос: "является ли ShipPlacementArray своего рода Ship?"

7 голосов
/ 22 февраля 2010

По моему опыту, каждый раз, когда я хотел удалить свойство из класса в унаследованном классе, мой дизайн класса был ошибочным. Одним из способов решения этой проблемы было бы создание нового базового класса без свойства ShipUnit, а затем наследование этого базового класса два раза, один раз для вашего конкретного типа Ship и один раз для вашего конкретного типа ShipPlacementArray. В обоих подклассах вы можете реализовать ShipUnit так, как вам нужно.

2 голосов
/ 22 февраля 2010

С модификатором new в C # вы можете скрыть унаследованный член от члена базового класса. Проверьте эту страницу для справки.

2 голосов
/ 22 февраля 2010

Вы не можете заставить членов базового класса исчезать в производном классе. В некоторых случаях вы можете mask или скрыть базовых членов, используя new ключевое слово на вашем скрытом члене в производном классе, но пользователь всегда сможет привести ваш объект обратно к базовому классу (base)instance_of_derived и получить доступ к членам базового класса.

Так, например, вы можете сделать в своем производном классе:

public new ShipUnit[][] shipUnit { get; set; }

Но тогда я могу сделать:

((Ship)ShipPlacementArray_instance).shipUnit

И это будет ссылаться на оригинальный shipUnit. Таким образом, вы можете «скрыть» участника, но не можете отключить его функциональность или доступность.

1 голос
/ 23 февраля 2010

«Сочетание композиции объекта с наследованием класса» - если вы ищете новое поведение в базовом классе, то не похоже, что вам все равно придется наследовать, потому что они разных типов. Возможно, Ship и ShipPlacementArray должны наследовать общий интерфейс, но, конечно, не от общего базового класса. Везде, где вам нужно будет использовать интерфейс, вы можете использовать интерфейс, но там, где вам нужна матрица ShipUnit, вы явно будете использовать тип ShipPlacementArray.

1 голос
/ 22 февраля 2010

Я не знаю, является ли это просто надуманным примером или реальной проблемой. Но я бы сказал, что наследство в этом случае нежелательно. У вас есть Ship и ShipPlacementArray. «Массив» в конце делает его более похожим на тип данных массива. Так что, забрав это, у вас есть ShipPlacement.

Мне кажется, это где-то где-то, так что, может быть, это член класса Корабль?

1 голос
/ 22 февраля 2010

В дополнение к другим отличным ответам, кроме того, я бы сказал, что инкапсуляция может оказаться лучшим вариантом. Часто я сначала думал, что хочу унаследовать от класса, а потом обнаружил, что действительно хотел его инкапсулировать. Это можно сделать, просто объявив новый экземпляр исходного класса в закрытом поле. Затем вы создаете открытые свойства и функции, которые просто вызывают исходный класс, как показано ниже, предоставляя вам тонкую часть контроля над тем, что раскрывается. Это также способ обойти недостатки наследования, такие как дополнительная сложность и невозможность выполнить множественное наследование (по уважительной причине):

class SomeNew
{
  private SomeOld someOld = new SomeOld();//could have done this in constructor instead

  public DoSomething()
  {
    someOld.DoSomething();
  }
}
0 голосов
/ 23 февраля 2010

вы можете использовать новое ключевое слово или добавить виртуальное в объявлении в базовом классе и переопределить его в производном классе.

0 голосов
/ 22 февраля 2010

Я не совсем понимаю, что вы хотите моделировать с наследованием, но я совершенно уверен, что это неправильный инструмент. Я предполагаю, что агрегация или состав - это то, что вам нужно.

0 голосов
/ 22 февраля 2010

Вы можете использовать ключевое слово new, например:

public new ShipUnit[][] shipUnit { get; set; }
...