风格的不同:IDictionary与Dictionary

rei*_*ein 68 .net c# java interface

我有一个朋友刚刚开始使用Java开发.NET开发很长时间,在查看了他的一些代码后,我注意到他经常做以下事情:

IDictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();
Run Code Online (Sandbox Code Playgroud)

他将字典声明为接口而不是类.通常我会做以下事情:

Dictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>();
Run Code Online (Sandbox Code Playgroud)

我只在需要时使用IDictionary接口(例如,将字典传递给接受IDictionary接口的方法).

我的问题是:他的做事方式有什么优点吗?这是Java中的常见做法吗?

Chr*_*ris 62

如果IDictionary是一个比Dictionary更"通用"的类型,那么在声明变量时使用更通用的类型是有意义的.这样您就不必太在意分配给变量的实现类,并且您可以在将来轻松更改类型,而无需更改大量以下代码.例如,在Java中,通常认为更好

List<Integer> intList=new LinkedList<Integer>();
Run Code Online (Sandbox Code Playgroud)

比它要做的

LinkedList<Integer> intList=new LinkedList<Integer>();
Run Code Online (Sandbox Code Playgroud)

这样我确定所有后续代码都将列表视为List而不是LinkedList,这样可以在将来轻松切换LinkedList for Vector或任何其他实现List的类.我会说这对Java来说很常见,而且编程也很好.

  • +1,但你可能想要使用'general'这个词,而不是'generic',它已经附加了一堆意义:) (22认同)

Jus*_*ner 27

这种做法不仅限于Java.

当你想要从你正在使用的类中解除对象的实例时,它也经常在.NET中使用.如果使用Interface而不是Class,则可以在需要时更改支持类型,而不会破坏其余代码.

您还会看到这种做法在处理IoC容器和使用Factory模式进行实例化时会大量使用.

  • 丢失Dictionary提供的功能,但IDictionary不是这个成语的重点.将本地变量声明为IDictionary会强制您将该变量的使用限制为可通过接口使用的变量.然后,如果您以后发现必须使用其他一些实现IDictionay而不是Dictionary的类,您可以通过更改调用具体类构造函数的一行来实现此目的(因为您知道您的代码仅将其用作IDictionary,而不是字典) ). (9认同)
  • 但是,如果您能够使用IDictionary ......那么您就不会使用该功能. (8认同)
  • 但是您会失去 Dictionary 可能提供的 IDictionary 中没有的所有功能。 (2认同)

Vit*_*sky 14

你的朋友遵循这个非常有用的原则:

"从实现细节中抽象出自己"

  • 不是真的,恕我直言.如果界面成员足够你,我真的建议你坚持使用界面.尽可能使代码尽可能通用. (7认同)
  • 但我们正在处理实施细节.我们不是在创建类的接口 - 我们只是声明一个局部变量. (6认同)

Sam*_*ell 8

对于已经是实现细节的局部变量和私有字段,最好使用具体类型而不是声明的接口,因为具体类提供了性能提升(直接调度比虚拟/接口调度更快).如果您没有在本地实现细节中不必要地转换为接口类型,JIT也将能够更容易地内联方法.如果从返回接口的方法返回具体类型的实例,则转换是自动的.

  • 这不是微观优化.您已经在实施中选择了具体的实现.为什么假装你没有牺牲性能? (7认同)
  • 这是一个微优化,只有在你有一个特定的性能瓶颈要解决时才应该执行,它不应该驱动设计. (4认同)

Tra*_*man 7

大多数情况下,您会看到成员暴露给外部代码时使用的接口类型 (IDictionary),无论是在程序集外部还是在类外部。通常,大多数开发人员在类定义内部使用具体类型,同时使用接口类型公开封装的属性。通过这种方式,他们可以利用具体类型的功能,但如果他们更改具体类型,则声明类的接口不需要更改。

公共类小部件
{
    私有字典<字符串,字符串>映射=新字典<字符串,字符串>();
    公共 IDictionary<string, string> 映射
    {
        获取{返回地图;}
    }
}

之后可以变成:

类 SpecialMap<TKey, TValue> : IDictionary<TKey, TValue> { ... }

公共类小部件
{
    private SpecialMap<字符串, 字符串> map = new SpecialMap<字符串, 字符串>();
    公共 IDictionary<string, string> 映射
    {
        获取{返回地图;}
    }
}

无需更改 Widget 的界面,也无需更改已使用它的其他代码。


Osc*_*Ryz 7

您应该始终尝试编程到接口而不是具体类.

在Java或任何其他面向对象的编程语言中.

在.NET中,通常使用一个I来表示你正在使用的接口.我认为这更常见,因为在C#中他们没有implements并且extends引用类和接口继承.

我想乳清会输入

 class MyClass:ISome,Other,IMore 
 { 
 }
Run Code Online (Sandbox Code Playgroud)

你可以告诉ISome一个IMore接口Other是一个类

在Java中,不需要这样的东西

 class MyClass extends Other implements Some, More {
 }
Run Code Online (Sandbox Code Playgroud)

这个概念仍然适用,您应该尝试编写接口.

  • 我不认为他的问题是关于接口或工作如何或者为什么从I开始.此外,基类必须在接口之前声明.因此,`public class MyClass:BaseClass,IFirstInterface,ISecondInterface`将是正确的.在界面的开头我没有任何天生的特殊之处.编译器不会以不同方式对待它.它是其他程序员的标记.您可以在没有它们的情况下命名接口 ..但其他程序员可能会讨厌你. (2认同)

use*_*341 6

IDictionary是一个接口,Dictionary也是一个类。

Dictionary实现IDictionary.

这意味着可以通过实例引用Dictionary实例IDictionary并通过实例调用大多数Dictionary方法和属性IDictionary

强烈建议尽可能多地使用接口,因为接口抽象了应用程序的模块和程序集,允许多态性,这在许多情况和情况下都是非常常见和有用的,并且允许用一个模块替换另一个模块而不接触其他模块。

假设现在,程序员写道:

IDictionary<string> dictionary = new Dictionary<string>();

现在dictionary调用 的方法和属性Dictionary<string>

将来数据库的规模越来越大,我们发现它Dictionary<string>太慢了,所以我们想用 替换Dictionary<string>RedBlackTree<string>这样更快。

因此,需要做的就是将上述指令替换为:

IDictionary<string> dictionary = new RedBlackTree<string>();

当然如果RedBlackTree实现了IDictionary,那么应用程序的所有代码都会成功编译,并且您拥有应用程序的较新版本,该应用程序现在比以前的版本执行得更快、更高效。

如果没有接口,这种替换将更加困难,并且需要程序员和开发人员更改更多可能出现错误的代码。


Ger*_*osz 5

据我所知,Java开发人员倾向于比.NET开发人员更频繁地使用抽象(和设计模式).这似乎是另一个例子:为什么在他基本上只使用接口成员时声明具体类?