[英]C# How to implement polymorphism in a functional style?
我有一些 OOP 代码,我想将其转换为功能样式,仅使用不可变类型且仅具有独立( static
)无副作用功能。
这是一个场景的简化版本:
abstract class Thing { }
class Sphere : Thing {
public readonly double Radius;
public Sphere(double r) { Radius = r; }
}
class Cube : Thing {
public readonly double Side;
public Cube(double s) { Side = s; }
}
之前, Thing
定义了一个抽象方法void Grow(double ratio)
。 我已将这两个具体实现转换为独立的 static 函数:
Sphere Grow(Sphere s, double ratio) => new Sphere(s.Radius*ratio);
Cube Grow(Cube c, double ratio) => new Cube(c.Side * ratio);
在 OOP 版本中,我可以使用多态性来枚举类型Thing
的集合并导致每个对象增长,例如:
things.foreach(x => x.Grow(r));
但是我怎样才能在函数式方法中做到这一点呢? 我知道我可以这样写:
Thing Grow(Thing t, double ratio) => t switch
{
Sphere s => Grow(s, ratio),
Cube c => Grow(c, ratio),
_ => throw new Exception()
};
和
things.Select(t => Grow(t, r))
但我不喜欢必须为我添加的每个新的 Thing 实现扩展 switch 表达式的想法。
我可以看到一种方法(我认为)使用反射来做到这一点,但出于其他原因我并不热衷于此。
有没有更简单的方法可以使用功能模式实现等效的 OOP 多态性? (在 C# 中,即 - 我知道它可以在例如 Haskell 中完成)。
尝试像这样为Grow
方法定义和使用通用接口。
interface IGrowable<T> where T: Thing {
T Grow(T t, double ratio);
}
class Sphere : Thing, IGrowable<Sphere> {
public readonly double Radius;
public Sphere(double r) { Radius = r; }
public Sphere Grow(Sphere s, double ratio) => new Sphere(s.Radius*ratio);
}
class Cube : Thing, IGrowable<Cube> {
public readonly double Side;
public Cube(double s) { Side = s; }
public Cube Grow(Cube c, double ratio) => new Cube(c.Side * ratio);
}
IEnumerable<IGrowable<T>> GrowOwn<T>(IEnumerable<IGrowable<T>> grows, double ratio){
return grows.Select(x => x.Grow(x,ratio));
}
编辑
如果要使用反射,定义这些 class
public abstract class Thing {}
public class Sphere : Thing {
public readonly double Radius;
public Sphere(double r) { Radius = r; }
public Sphere(Sphere s, double ratio){ Radius = s.Radius * ratio; }
}
public class Cube : Thing {
public readonly double Side;
public Cube(double s) { Side = s; }
public Cube(Cube c, double ratio){ Side = c.Side * ratio; }
}
和这个。
T Grow<T>(T thing, double ratio) where T: Thing => (T)Activator.CreateInstance(typeof(T) , thing, ratio);
您可以从此 function 获得Thing
object。
但是存在MissingMethodException
的风险。 而且反射不快。
( 请参阅 .NET 的设计目标,使用表达式树可能有助于提高处理速度)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.