Доступ к конкретным атрибутам абстрактного объекта? - PullRequest
1 голос
/ 22 декабря 2010

Я думаю, что это довольно простой вопрос, но если я хочу, чтобы объект владел другим объектом типа A или B, как приложение, использующее этот объект, может получить доступ к определенным атрибутам? Э.Г.

public abstract class Animal
{
     private int Age;
     // Get Set
}

public class Tiger: Animal
{
     private int NoStripes;
     // Get Set
}

public class Lion : Animal
{
     private bool HasMane;
     // Get Set
}

public class Zoo
{
     private Animal animal;
     // Get Set
}

public static void Main()
{
     Zoo zoo = new Zoo();
     zoo.animal = new Tiger();

     // want to set Tiger.NoStripes
}

Ответы [ 3 ]

2 голосов
/ 22 декабря 2010

Вам придется разыграть zoo.Animal до Tiger

Или вы можете попробовать что-то вроде

public abstract class Animal
{
    public int Age;
    // Get Set
}

public class Tiger : Animal
{
    public int NoStripes;
    // Get Set
}

public class Lion : Animal
{
    public bool HasMane;
    // Get Set
}

public class Zoo<T> where T : Animal
{
    public T animal;
    // Get Set
}

Zoo<Tiger> zoo = new Zoo<Tiger>();
zoo.animal = new Tiger();
zoo.animal.NoStripes = 1;
0 голосов
/ 22 декабря 2010

Это суть наследования и полиморфизма.

Если вы можете определить, что экземпляр Animal на самом деле является экземпляром Tiger, вы можете разыграть его:

((Tiger)zoo.Animal).NoStripes = 1;

Однако, если вы попытаетесь сделать это на экземпляре Animal, который не является Tiger, вы получите исключение времени выполнения.

, например:

Zoo zoo = new Zoo();
zoo.animal = new Tiger();
((Tiger)zoo.Animal).NoStripes = 1; //Works Fine

((Lion)zoo.Animal).NoStripes = 1; //!Boom - The compiler allows this, but at runtime it will fail.

Существуетальтернативный синтаксис приведения, использующий ключевое слово «as», которое возвращает ноль, а не исключение в случае сбоя приведения.Это звучит замечательно, но на практике вы, скорее всего, получите незначительные ошибки позже, когда будет уничтожен нулевой объект.

Tiger temp = zoo.Animal as Tiger; //This will not throw an exception
temp.NoStripes = 1; //This however, could throw a null reference exception - harder to debug
zoo.Animal = temp;

Чтобы избежать исключения нулевой ссылки, вы можете проверить нуль, конечно

Tiger temp = zoo.Animal as Tiger; //This will not throw an exception
if (temp != null)
{
    temp.NoStripes = 1; //This however, could throw a null reference exception - harder to debug
    zoo.Animal = temp;
}
0 голосов
/ 22 декабря 2010

Прямой ответ:

public static void Main() {
    Zoo zoo = new Zoo();
    zoo.animal = new Tiger();

    ((Tiger)zoo.Animal).NoStripes = 10;
}

Конечно, чтобы это работало, вам нужно знать, что zoo.Animal на самом деле Tiger.Вы можете использовать zoo.Animal is Tiger для проверки этого (хотя оператор as предпочтительнее, чем is).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...