I've been implementing visitor pattern in C#. What I have is:
Hierarchy of classes:
public class A {
public virtual void Accept(Visitor visitor)
{
visitor.Visit(this);
}
}
public class B : A {
public override void Accept(Visitor visitor)
{
visitor.Visit(this);
}
}
The Visitor
class:
public abstract class Visitor {
public virtual void Visit(A item) {
//...
}
public virtual void Visit(B item) {
Visit(item as A);
}
}
Concrete Visitor
class:
public class ConcreteVisitor : Visitor {
public override void Visit(B item) {
// do something
// and call Visit for base class
Visit(item as A); // I need to know type A.
}
}
Is there any way to call Visit
for item
's base class without knowing its direct base class name? I would like to be able to change hierarchy without changing ConcreteVisitor
class.
Thank you
Make it the responsibility of A
. With a method for example:
public class A {
public virtual void Accept(Visitor visitor)
{
visitor.Visit(this);
}
public A AsBase()
{
return this;
}
}
and
public class ConcreteVisitor : Visitor {
public override void Visit(B item) {
// do something
// and call Visit for base class
Visit(item.AsBase()); // convert to base type
}
}
PS: your design is maybe a bit odd, but I was challenged by your question ;)
I really believe that there's a simpler solution which involves changing visitor's method identifiers:
public class ConcreteVisitor : Visitor {
public override void VisitB(B item) {
VisitA(item);
}
}
As B
is A
, the upcast is implicit .
For example, a real case might be:
public abstract class CarVisitor
{
public virtual Engine VisitEngine(Engine engine) => engine;
public virtual DieselEngine VisitDieselEngine(DieselEngine engine) => engine;
}
public sealed class MyCarVisitor : CarVisitor
{
public override DieselEngine VisitDieselEngine(DieselEngine engine)
{
VisitEngine(engine);
return engine;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.