Как я могу использовать GetType для доступа к методам / свойствам производных классов в C #? - PullRequest
1 голос
/ 04 января 2011

У меня есть два производных класса, Dog и Bird, которые происходят от базового класса Animal.

Собака имеет свойство Кеннел, а Птица имеет свойство Гнездо.

Мне нужен метод (в отдельном статическом классе), который может получать экземпляр класса Animal, проверять тип и затем вызывать другие методы, для которых Kennel или Nest передаются в качестве параметров, что-то вроде:

if (MyAnimal.GetType = Dog)
{MyKennelMethod(MyAnimal.Kennel)}
else if (MyAnimal.GetType = Bird)
{MyNestMethod(MyAnimal.Nest)}

Полагаю, это не сработает. Есть ли способ получить доступ к свойствам производного класса, когда у вас есть только базовый класс? Если возможно, я бы предпочел не загромождать классы Dog и Bird отдельными абстрактными методами, так как я бы предпочел отдельный статический класс для обработки всех методов. Я также хотел бы, чтобы это было легко масштабируемым, чтобы я мог иметь сотни различных новых «животных», происходящих из Animal.

Извините за ошибки в синтаксисе кода, на данный момент у меня нет редактора.

Ответы [ 4 ]

4 голосов
/ 04 января 2011

Конечно, нет проблем.

Dog dog = myAnimal as Dog;
Bird bird = myAnimal as Bird;
if (dog != null)
   KennelMethod(dog.Kennel);
else if (bird != null)
   NestMethod(bird.Nest);

Однако я бы рекомендовал избегать этой ситуации в первую очередь.Если у вас есть метод, который принимает животное, но на самом деле ожидает собаку или птицу, то это звучит так, как будто вы действительно хотите два метода , один из которых принимает собаку, а другой - птицу.1007 *

Если возможно, я бы не стал загромождать классы Dog и Bird отдельными абстрактными методами.Я также хотел бы, чтобы это было легко масштабируемым, чтобы у меня могли быть сотни различных «животных», происходящих из Animal.

Ваши требования несколько противоречивы;Вы не хотите кодировать информацию об иерархии типов в самом коде типа , поэтому этот материал должен находиться за пределами иерархии типов, и поэтому у вас есть проблема с масштабируемостью.

Вы рассматривали использование шаблона посетителя?Это довольно стандартный способ виртуальной диспетчеризации типа объекта во время выполнения, но с кодом, который фактически выполняется, существующим вне класса.

3 голосов
/ 04 января 2011

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

public static void DoSomething(Animal animal)
{
    if (animal is Dog)
    {
      MyKennelMethod((animal as Dog).Kennel);
    }
    else if (animal is Bird)
    {
      MyNestMethod((animal as Bird).Nest);
    }
}

Этот подход нарушает цель наследования. Правильный путь - выставление общего свойства в родительском объекте (животном). Это очень простой пример. Вы можете определить общий тип для Home, и каждый дочерний объект предоставляет его по-разному:

public abstract class Animal
{
    public abstract string Home;
}

public class Dog : Animal
{
   public override string Home = "Kennel";
}

public class Bird : Animal
{
   public override string Home = "Nest";
}
2 голосов
/ 04 января 2011

Вы должны разыграть:

void SomeMethod(Animal animal)
{
    var dog = animal as Dog;
    var bird = animal as Bird;

    if (dog != null)
    {
        // it's a dog - do whatever you want with the dog
    }

    if (bird != null)
    {
        // it's a bird - do whatever you want with the bird
    }
}

Однако, это запах кода. Вероятно, есть более хороший способ разработки ваших классов, так что такой тип кастинга не нужен. Например, Animal может предоставлять свойство Home, которое возвращает Kennel, когда это Dog, и Nest, когда это Bird. Или, может быть, ваш статический метод должен просто взять Dog, а затем иметь перегрузку, которая принимает Bird.

0 голосов
/ 04 января 2011

Полагаю, что питомник, гнездо и методы, которые используют их в качестве параметров, имеют что-то общее, верно?Если это так, я предлагаю интерфейс:

interface SweetHome
{ 
    // members
}

class Dog: Animal
{
    public SweetHome Kennel { get; set; }
}

class Bird: Animal
{
    public SweetHome Nest { get; set; }
}

Это может удовлетворить ваши потребности.Но я все еще думаю, что методы должны быть расположены в классах, производных от Animal, а не в каком-то статическом классе снаружи.

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