Наследование и класс обслуживания - PullRequest
0 голосов
/ 22 декабря 2010

Это, я думаю, что-то основное в ООП:

Среда: C # /. Net 2.0

Допустим, у меня есть два класса:

public class Animal
{

}
public class Dog : Animal
{

}

Класс обслуживания с двумя методами:

 public void DoStuff(Animal animal)
    {
        Console.Write("Animal stuff");
    }
    public void DoStuff(Dog animal)
    {
        Console.Write("Dog stuff");
    }

Если я выполню следующий код:

 Animal instance = new Animal();
        MyService.DoStuff(instance);

        Animal instance2 = new Dog();
        MyService.DoStuff(instance2);

«Вещи животных» напечатаны дважды.

Итак, мой вопрос: почему? И как я могу получить "Animal stuff" и "Dog stuff" без приведения instance2 или перемещения метода из моего сервиса в мой класс (на самом деле я хотел бы, чтобы мой код работал, но это не так: ()

Спасибо

PS: Это всего лишь пример:)


Поскольку шаблон Visitor не очень привлекателен, я просто перенесу метод моего сервиса в свой класс, ожидая лучшего решения.

Ответы [ 3 ]

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

Причина в том, что второй вызов, хотя и проходит с собакой, передает ссылку животному. Эта ссылка может быть любым типом животного (вы просто передали Dog), но .NET этого не знает, поэтому она должна вызывать версию метода, которая принимает ссылку на Animal, а не более конкретную ссылку.

1 голос
/ 23 декабря 2010

Другая вещь, которая может показаться хаком, - привести переданный параметр к dynamic.Это позволило бы вам реализовать «динамический посетитель», например, чтобы вы написали

foreach (dynamic a in animals)
  doStuff(a);

void doStuff(Animal a) { ... }
void doStuff(Dog d) { ... }

и т. Д.

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

Вы не переопределяете метод doStuff () в Dog, потому что тип параметра отличается.Это два отдельных метода.

Либо измените подпись в Dog, чтобы она соответствовала Animal, либо создайте посетителя, который разберется с вами.

Вот один способ написать это:

public interface Animal {  void accept(AnimalVisitor visitor); }

public class AbstractAnimal : Animal
{
    public void accept(AnimalVisitor visitor) { visitor.visit(this); } 
}

public class Dog : AbstractAnimal {}

public class Cat : AbstractAnimal {}

public interface AnimalVisitor
{
    void visit(Animal animal);
    void visit(Dog dog);
    void visit(Cat cat);
}

Теперь служба (и все остальные) может реализовывать AnimalVisitor и выполнять разные действия с каждым подтипом Animal.

Это общий шаблон, называемый "двойная отправка";Вы можете прочитать больше об этом в «Более эффективном C ++» Скотта Мейерса.

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