背景知识
将接口视为合同。在两个人之间的合同中,它定义了所涉及的各方的能力和期望。在编程中,它的工作方式相同。接口定义了期望什么,必须存在什么才能符合该接口。因此,由于它只定义了预期的内容,它本身并没有提供实现,可以说是“幕后代码”。
属性的行为类似于字段,但允许您在有人为其分配值或读取值时进行拦截。您也可以拒绝读取或写入它,这是您定义属性时的选择。因此,接口使用属性而不是字段。由于“合同”只是定义应该存在的属性(名称和类型),并且如果它应该允许读取或写入功能,则由实现者来提供它。
以.NET 框架中的IEnumerator接口为例。该接口旨在允许对对象集合进行迭代。目的不是更改项目或随机访问它们,它只是为了获取对象 A 并根据需要多次移动到下一个、下一个、下一个。许多集合类型类实现了这一点:Queue、ArrayList、SortedList、Stack 等。所有这些类型的对象都存储了许多对象,现在它们都共享一个共同的“契约”:能够逐个迭代它们。
但是,您可以看到该IEnumerator
接口MoveNext()
声明了一个方法。为什么?这是因为这些项目可能不会以相同的方式提供。例如,人们通常会从第一项到最后一项访问 ArrayList。但是 aStack
的设计正好相反,人们可以访问最后一个对象到第一个对象。
已回答的问题
有了所有这些知识,将变量声明为接口类型而不是实现接口的类类型的局限性在于,您只能访问接口(合同)所说的应该存在的内容。但好处是您可以将任何实现该接口的类类型分配给此变量。