C#有抽象类和接口,是否也应该有;混合;?
每隔一段时间,我就会遇到这样一种情况:我希望一组类都具有相似的逻辑。例如,我可能希望鸟和飞机都能飞行。如果您考虑的是“策略模式”,我会同意,但即使使用策略,有时也无法避免重复代码 例如,假设以下情况适用(这与我最近遇到的实际情况非常相似):C#有抽象类和接口,是否也应该有;混合;?,c#,visual-studio,design-patterns,oop,C#,Visual Studio,Design Patterns,Oop,每隔一段时间,我就会遇到这样一种情况:我希望一组类都具有相似的逻辑。例如,我可能希望鸟和飞机都能飞行。如果您考虑的是“策略模式”,我会同意,但即使使用策略,有时也无法避免重复代码 例如,假设以下情况适用(这与我最近遇到的实际情况非常相似): Bird和Airplane都需要保存实现IFlyBehavior的对象实例 调用OnReadyToFly()时,Bird和frame都需要请求IFlyBehavior实例执行Fly() 调用OnReadyToLand()时,Bird和frame都需要向IFl
Bird
和Airplane
都需要保存实现IFlyBehavior
的对象实例OnReadyToFly()
时,Bird
和frame
都需要请求IFlyBehavior
实例执行Fly()
OnReadyToLand()
时,Bird
和frame
都需要向IFlyBehavior
实例询问Land()
OnReadyToFly()
和onreadytofland()
是私有的鸟
继承动物
和飞机
继承人兽
Moth
,hotirballoon
,以及其他16个对象,假设它们都遵循相同的模式
我们现在需要20份以下代码的副本:
private IFlyBehavior _flyBehavior;
private void OnReadyToFly()
{
_flyBehavior.Fly();
}
private void OnReadyToLand()
{
_flyBehavior.Land();
}
有两件事我不喜欢:
IFlyBehavior
中添加了一个BankRight()
,那么我们需要将更改分发给所有20个类ICrashable
,所以抽象基类并不总是可行的解决方案)模式
或模板
或[在这里填写您的想法],它就像一个接口,但允许您在成员上放置私有或受保护的访问修饰符,该怎么办?您仍然需要为每个类提供一个实现,但是如果您的类实现了PFlyable
模式,那么您至少可以强制每个类都有必要的样板代码来调用Fly()
和Land()
。而且,使用像VisualStudio这样的现代IDE,您可以使用“ImplementPattern”命令自动生成代码
就我个人而言,我认为将接口的含义扩展到任何合同,无论是内部(私有/受保护)还是外部(公共)都更有意义,但我建议首先添加一个全新的结构,因为人们似乎对“接口”一词的含义非常坚定,我不想让语义学成为人们回答的焦点
问题:
不管你怎么称呼它,我想知道我在这里建议的功能是否有意义。我们是否需要某种方法来处理由于限制性访问修饰符的需要或程序员无法控制的原因而无法提取出所需代码的情况
更新
从AakashM的评论中,我相信我所要求的功能已经有了一个名字:混音。所以,我想我的问题可以缩短为:“C是否应该允许混入?”你刚才描述的
一个流行的C#AOP实现似乎是(主站点似乎关闭了/对我来说不起作用,直接的“关于”页面)
后续评论:我不确定PostSharp是否支持,但我认为你在谈论AOP: 类型间声明提供了一种方法 表达横切关注点 影响模块的结构。 这也被称为开放类 使程序员能够在一个 安置另一个人的成员或父母 类,通常是为了合并 与中某个问题相关的所有代码 一方面
VisualStudio已经提供了带有代码片段的“穷人表单”。此外,有了重构工具a la ReSharper(甚至可能还有visualstudio中的原生重构支持),在确保一致性方面还有很长的路要走 [编辑:我没有想到扩展方法,这种方法让你走得更远(你只需要将_flyBehavior作为一个私有变量)。这使得我的其余答案可能过时了…] 但是,;只是为了讨论:如何改进?这是我的建议 可以想象,未来版本的C#编译器将支持以下内容:
// keyword 'pattern' marks the code as eligible for inclusion in other classes
pattern WithFlyBehaviour
{
private IFlyBehavior_flyBehavior;
private void OnReadyToFly()
{
_flyBehavior.Fly();
}
[patternmethod]
private void OnReadyToLand()
{
_flyBehavior.Land();
}
}
然后你可以用它,比如:
// probably the attribute syntax can not be reused here, but you get the point
[UsePattern(FlyBehaviour)]
class FlyingAnimal
{
public void SetReadyToFly(bool ready)
{
_readyToFly = ready;
if (ready) OnReadyToFly(); // OnReadyToFly() callable, although not explicitly present in FlyingAnimal
}
}
这会是一种进步吗?可能真的值得吗?也许…我们不能为此使用扩展方法吗
public static void OnReadyToFly(this IFlyBehavior flyBehavior)
{
_flyBehavior.Fly()
}
这模仿了您想要的功能(或混合)您描述的问题可以使用访问者模式解决(所有问题都可以使用访问者模式解决,所以要小心!) 访问者模式允许您将实现逻辑移到一个新类中。这样,您就不需要基类,访问者在不同的继承树上工作得非常好 总而言之:
public interface IFlyer
{
public IFlyBehavior FlyBehavior
}
public Bird : IFlyer
{
public IFlyBehaviour FlyBehavior {get;set;}
}
public Airplane : IFlyer
{
public IFlyBehaviour FlyBehavior {get;set;}
}
public IFlyerExtensions
{
public void OnReadyToFly(this IFlyer flyer)
{
flyer.FlyBehavior.Fly();
}
public void OnReadyToLand(this IFlyer flyer)
{
flyer.FlyBehavior.Land();
}
}