C# 禁止现有类的接口实现有什么好处吗?
在静态OOP语言中,使用接口来声明几个类共享一些逻辑属性——它们是一次性的,可以与C# 禁止现有类的接口实现有什么好处吗?,c#,oop,haskell,interface,programming-languages,C#,Oop,Haskell,Interface,Programming Languages,在静态OOP语言中,使用接口来声明几个类共享一些逻辑属性——它们是一次性的,可以与int进行比较,可以序列化,等等 比如说,.net没有标准的IDisposable界面,我刚刚想出了一个好主意: interface IDiscardable { void Discard(); } 我的应用程序使用了大量的System.Windows.Forms,我认为Form满足了idiscarable的逻辑要求。问题是,Form是在我的项目之外定义的,所以C#(和Java,C++…)不允许我为它实现idis
int
进行比较,可以序列化,等等
比如说,.net
没有标准的IDisposable
界面,我刚刚想出了一个好主意:
interface IDiscardable { void Discard(); }
我的应用程序使用了大量的System.Windows.Form
s,我认为Form
满足了idiscarable
的逻辑要求。问题是,Form
是在我的项目之外定义的,所以C#
(和Java
,C++
…)不允许我为它实现idiscarable
C#
不允许我正式表示表单
可以被丢弃的事实(我可能会得到一个MyForm
包装类或其他东西)
相比之下,Haskell
有typeclass
,它们在逻辑上类似于接口。Show
实例可以作为字符串呈现(或序列化),Eq
允许比较等。但有一个关键区别:您可以编写一个typeclass实例(类似于实现接口)没有访问类型的源代码。因此,如果Haskell
为我提供了一些表单
类型,那么为它编写一个可丢弃的
实例就很简单了
我的问题是:从语言设计师的角度来看,第一种方法有什么优势吗?Haskell
不是一种面向对象的语言-第二种方法是否在任何方面违反了OOP
谢谢!您所描述的是适配器模式。以新类型构成对象的行为,为基础类型提供一些额外的行为,在本例中是另一个接口的实现
与许多设计模式一样,不同的语言选择不同的设计模式直接融入语言本身,并提供特殊的语言支持,通常以更简洁的语法形式提供,而其他模式需要通过使用其他机制来实现,而无需使用其自身的特殊语法
C#对适配器模式没有特殊的语言支持,您需要创建一个新的显式类型来组合其他类型,实现接口,并使用组合的类型来实现接口的契约。他们是否可以向语言中添加这样的功能,当然。与现有的任何其他功能请求一样eds将被设计、实施、测试、记录,以及各种其他费用。此功能(到目前为止)没有成功。好吧,Haskell方法确实有一个缺点,例如,当您编写两个不同的库时,每个库为相同的外部类型(由第三个库提供)提供自己的接口Foo
实现.在这种情况下,这两个库不能在同一个程序中同时使用。因此,如果你把缺乏缺点称为优势,那么我想这将是OOP语言实现这一点的一个优势,但这是一个相当弱的优势
然而,我要补充的是,Haskell类型类有点像OOP接口,但并不完全像它们。但类型类也有点像策略和模板方法模式;可以通过显式传递“字典”来模拟类型类对象,该对象为类型类操作提供实现。因此,以下Haskell类型类:
class Monoid m where
mempty :: m
mappend :: m -> m -> m
…可以使用此显式字典类型进行模拟:
data Monoid_ m = Monoid_ { _mempty :: m, _mappend :: m -> m -> m }
…或像这样的OOP接口:
interface Monoid<M> {
M empty();
M append(M a, M b);
}
接口幺半群{
M空();
M追加(ma,mb);
}
类型类在此基础上添加的是编译器将隐式地维护和传递字典。有时在Haskell社区中,您会得到关于类型类何时以及是否优于显式字典传递的参数;例如,请参见Gabriel Gonzalez的博客条目(请记住,他并不是100%同意他在那里说的话!)因此,与此想法相对应的OOP将不是扩展语言以允许外部实现
声明,而仅仅显式使用策略或模板方法有什么缺点?您描述的内容在短语后面称为duck typing“如果它像鸭子一样走路,像鸭子一样游泳,像鸭子一样呱呱叫,那么它就是鸭子。”
C#实际上允许通过dynamic
关键字进行动态(运行时)duck键入,但不允许静态(编译时)duck键入
您可能需要Microsoft的人员提供C#中不存在这种情况的确切原因,但以下是一些可能的候选人:
- 添加特性的理念。特性没有缺点是不够的,为了证明在实现、测试、维护和支持语言特性方面所做的努力是合理的,它必须提供明显的好处。在
动态
关键字和适配器模式之间,没有很多情况下可以使用它l、 反射也足够强大,可以有效地提供duck类型,例如,我相信使用Castle的DynamicProxy会相对简单
- 在某些情况下,您希望类能够指定如何访问它。例如,fluent API通常通过使用接口来控制类上链接方法的有效顺序和组合。例如,请参阅。如果我的fluent类是围绕一个语法设计的,该语法说明once method
a
是called,除了B
之外,没有其他方法可以调用,我可以控制它
public class FluentExample : ICanCallAB
{
public ICanCallB A()
{
return this;
}
public ICanCallAB B()
{
return this;
}
}
public interface ICanCallA
{
void A();
}
public interface ICanCallAB : ICanCallA
{
void B();
}