Мне нужна помощь по этому ключевому слову и наследованию
abstract class BaseClass
{
public virtual void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
class DerivedClass: BaseClass
{
}
interface IVisitor
{
void Visit(BaseClass baseEntity);
void Visit(DerivedClass derivedEntity);
}
class Visitor : IVisitor
{
public void Visit(DerivedClass derivedEntity)
{
Debug.WriteLine("Derived Entity visited");
}
public void Visit(BaseClass baseEntity)
{
Debug.WriteLine("Base Entity visited");
}
}
После вышеупомянутых заявлений
class Program
{
static void Main(string[] args)
{
DerivedClass derived = new DerivedClass();
Visitor visitor = new Visitor();
derived.Accept(visitor);
}
}
производит
"Base Entity visited"
Однако я ожидаю, что это произведет
"Derived Entity visited"
- Кто-нибудь может объяснить почему?
- Что я должен сделать, чтобы создать "Derived Entity посещения"? Я не хочу отменять функцию "Принять".
2 ответа
Проблема, с которой вы здесь сталкиваетесь, заключается в многократной диспетчеризации. Компилятор выбирает базовый класс, потому что вы вызываете его из базового класса. Одним из быстрых решений, которое вы можете добавить, является использование dynamic
:
public virtual void Accept(IVisitor visitor)
{
visitor.Visit(this as dynamic);
}
Вы обманываете компилятор, чтобы он не знал фактический тип объекта, и вызываете корректную перегрузку Визита.
И вот некоторые дополнительные чтения из MSND
Перегрузки разрешаются во время компиляции, поэтому при компиляции BaseClass
компилятор выберет Visitor.Visit
перегрузка, которая соответствует типу времени компиляции (BaseClass
).
При использовании шаблона посетителя вы, как правило, хотите переопределить Accept
метод в производных классах.
Хотя вы можете избежать этого, используя dynamic
вы потеряете преимущество статической проверки типов, если вы это сделаете.
В этой статье показан пример шаблона посетителя в C#, где Accept
Метод переопределяется в производных классах.