不修改重载方法类
Overloading method without modifying classes
我可以访问一个class结构,我不能修改它,如下:
Graphics
Circle
Line
etc.
同样,我不能修改它!这些都有各自的属性,例如 Radius
、FirstPoint
、LastPoint
等,以及一些共同的属性。
我想创建一个接受 Graphics
对象的方法,根据对象的类型,将 运行 一个 ToJson
方法:
Graphics g = db.GetGraphic(123);
// Console.WriteLine(g.GetType()) prints "Circle"
// Should run some specific implementation for `Circle` type graphics, and
// have an overload for all types including Graphics
ToJson(g);
起初我想我可以巧妙地重载 ToJson
方法:
ToJson(Graphics g) { ... }
ToJson(Circle g) { ... }
ToJson(Line g) { ... }
然而,这当然适用于每次通用 ToJson(Graphics)
重载。
我确定我可以执行以下操作:
if (g is Circle) ...
if (g is Line) ...
if (g is Graphics) ...
或者创建一个字典来降低每种类型的复杂性,但这并不是最好的做事方式
我考虑过的
我考虑过是否可以在每个对象周围使用一些通用包装方法(例如,new JsonGraphics(g).ToJson()
),但我不想自己执行任何手动类型检查。
我查看了双重调度和访问者模式,但我不确定它们是否满足我的要求,因为它们看起来我必须修改这些 classes(或者我可能只是没有完全理解它们),并且(有点明显,但是)泛型也基本上不在 window 范围内,因为它们要求我提前知道这是什么类型的 Graphics
对象。
那么两个问题:
除了使用某些词典或其他 if (g is Type)
之类的东西之外,还有更好的方法吗?
如果我可以修改 classes,图案会是什么样子?在这种情况下这是不可能的,但是在我可以的情况下,double dispatch/visitor 是最好的方法吗?
无法修改基础 class,或者无法在具体类型变成通用 Graphics
类型之前访问具体类型,不幸的是,我认为您无能为力,除了检查 Graphics
对象的运行时类型。
您可以使用 switch 语句(自 C# 7.0 起),它比您的 if
链稍微干净一些:
switch (g)
{
case Circle circle: ... break;
case Line line: ... break;
default: /* Oh no! */ break;
}
就我个人而言,我不认为使用 Dictionary 比这样的 switch 语句有多少优势 - 两者都可以放入一个小的独立方法中(因此减少 amount 违反了 open/close 原则),但转换会便宜得多。
您还可以使用 dynamic
,这会导致运行时进行后期绑定:
dynamic d = g;
ToJson(d); // Picks the right ToJson overload corresponding to the runtime type of 'd'
...虽然,dynamic 有相当大的运行时成本,通常被认为是异味。
我可以访问一个class结构,我不能修改它,如下:
Graphics
Circle
Line
etc.
同样,我不能修改它!这些都有各自的属性,例如 Radius
、FirstPoint
、LastPoint
等,以及一些共同的属性。
我想创建一个接受 Graphics
对象的方法,根据对象的类型,将 运行 一个 ToJson
方法:
Graphics g = db.GetGraphic(123);
// Console.WriteLine(g.GetType()) prints "Circle"
// Should run some specific implementation for `Circle` type graphics, and
// have an overload for all types including Graphics
ToJson(g);
起初我想我可以巧妙地重载 ToJson
方法:
ToJson(Graphics g) { ... }
ToJson(Circle g) { ... }
ToJson(Line g) { ... }
然而,这当然适用于每次通用 ToJson(Graphics)
重载。
我确定我可以执行以下操作:
if (g is Circle) ...
if (g is Line) ...
if (g is Graphics) ...
或者创建一个字典来降低每种类型的复杂性,但这并不是最好的做事方式
我考虑过的
我考虑过是否可以在每个对象周围使用一些通用包装方法(例如,new JsonGraphics(g).ToJson()
),但我不想自己执行任何手动类型检查。
我查看了双重调度和访问者模式,但我不确定它们是否满足我的要求,因为它们看起来我必须修改这些 classes(或者我可能只是没有完全理解它们),并且(有点明显,但是)泛型也基本上不在 window 范围内,因为它们要求我提前知道这是什么类型的 Graphics
对象。
那么两个问题:
除了使用某些词典或其他 if (g is Type)
之类的东西之外,还有更好的方法吗?
如果我可以修改 classes,图案会是什么样子?在这种情况下这是不可能的,但是在我可以的情况下,double dispatch/visitor 是最好的方法吗?
无法修改基础 class,或者无法在具体类型变成通用 Graphics
类型之前访问具体类型,不幸的是,我认为您无能为力,除了检查 Graphics
对象的运行时类型。
您可以使用 switch 语句(自 C# 7.0 起),它比您的 if
链稍微干净一些:
switch (g)
{
case Circle circle: ... break;
case Line line: ... break;
default: /* Oh no! */ break;
}
就我个人而言,我不认为使用 Dictionary 比这样的 switch 语句有多少优势 - 两者都可以放入一个小的独立方法中(因此减少 amount 违反了 open/close 原则),但转换会便宜得多。
您还可以使用 dynamic
,这会导致运行时进行后期绑定:
dynamic d = g;
ToJson(d); // Picks the right ToJson overload corresponding to the runtime type of 'd'
...虽然,dynamic 有相当大的运行时成本,通常被认为是异味。