Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 禁止现有类的接口实现有什么好处吗?_C#_Oop_Haskell_Interface_Programming Languages - Fatal编程技术网

C# 禁止现有类的接口实现有什么好处吗?

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

在静态OOP语言中,使用接口来声明几个类共享一些逻辑属性——它们是一次性的,可以与
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();
    }