最近我在接受采访时被问到,接口是否可以被视为C#中的一个类?即接口是C#中的一个类吗?
我很困惑。
答案是什么?
答案 0 :(得分:8)
不,界面不是一个类。
接口是一组方法签名,可能还有与单个想法相关的属性。例如,IList接口将具有索引,插入和获取元素数量的方法。但是,它没有定义任何实现细节。列表接口可以实现为链接列表,包装数组或任何您想要的,只要它在接口中定义这些方法。
类是用于创建实际对象的模板。类是方法签名的集合,以及这些方法的实现。
所以不,接口不是类,因为它只定义了一个特定的契约,而一个类定义了对象的整个行为。
Commenter SquareCog准确地指出上述情况并非完全正确。由于类可以被子类化,并且方法被重写,因此类与对象的实际行为的关系变得更加复杂。我只是通过说类是个体实体来解决这个问题。您可以阅读类的源代码并了解该类包含的行为。但是,在运行时,对象具有类型而不是类。类型是整个继承树,而不是单个类,因此可以在几个不同的类上定义类型的行为。幸运的是,这并没有改变接口是可以暗示(通过名称,参数类型等)某些实现的契约的基本概念差异,但是除了方法签名之外不能强制执行任何操作,而类确实定义了一个实现,即使这不是在运行时使用的实际实现。
答案 1 :(得分:3)
从逻辑角度来看,它们非常相似。正如其他人所指出的那样,只有公共抽象成员的ABC 1 与接口的用途几乎相同。
当你了解它的具体细节时,两者有许多重要的区别。
1:抽象基类
答案 2 :(得分:2)
是的,任何不包含实现且仅由抽象方法组成的抽象类都等同于接口。
答案 3 :(得分:2)
Java接口不是类;它是需要由类实现的方法声明;能力的描述,如果你愿意的话。 Java中的抽象类是适当的类和接口之间有趣的中间点,因为它们定义了可用的方法,但也提供了一些默认实现。
Java中抽象类和接口之间的根本区别在于,您只能扩展一个类;你可以实现多个接口。 抽象类描述你是什么;界面描述了您可以做的事情。你也可以定义你能做什么 - 但它具有更强的意义。
答案 4 :(得分:1)
可能有几个答案。
不,类不是接口 - 接口定义合约,类是可以创建的对象类型。
是的,可以将接口视为仅使用虚方法的基类 - 这就是在C ++中定义接口的方式。
答案 5 :(得分:1)
通常,接口是一种类,可以由类实现,以指示类通过一组方法公开行为。例如,.Net有一个ICollection
接口,其中包含与集合交互的方法。
在C ++中,接口是一个每个方法都是抽象的类。
在Java和.Net中,接口是与类无关的独立类型。
无论哪种方式,类都可以实现接口。
答案 6 :(得分:0)
将.net视为在.net中有三种“安全”类型是有帮助的:接口,类和值类型(还有像指针这样的东西,但那些是另一个故事),以及三个主要可以使用上下文类:存储位置,堆对象和通用约束。
堆对象可以是任何类型,但所有堆对象的行为都类似于对象。接口类型的堆对象很少见;它们通常不在.net中创建,但可以由设计用于较旧对象模型的代码创建。类类型的堆对象包含每个字段的一个存储位置;值类型的堆对象包含一个存储位置,其类型是有问题的值类型。
存储位置同样可以是任何类型,但值类型存储位置与其他位置不同。类类型或接口类型的存储位置包含类引用。值类型存储位置包含值原语(字节,整数,字符,浮点数等),或者包含值类型的每个字段的存储位置(例如,类型{的存储位置{1}}保存两个类型为Point
的存储位置,每个位置都包含一个带符号的32位整数原语。
通用约束也可以是任何类型,但是接口类型的约束不会将约束泛型类型参数本身限制为类类型,接口类型或值类型。可以使用类类型,接口类型或值类型的参数调用声明为Int32
的方法。如果使用value-type参数调用例程,则void Foo<T>(T param) where T:IWowzo
和声明为param
类型的任何其他存储位置将存储为值类型。如果使用类类型或整数类型的参数调用例程,则T
和声明为类型param
的任何其他存储位置将存储为类引用。重要的是要注意,如果T
本身是一个接口类型(T
或派生类型),那么IWozo
将作为对象的引用传递,并且无论如何都会表现为对象实例的类型是类对象还是值类型。如果struct param
实现Bar
,而IWowzo
是myBar
类型的变量,则调用Bar
可能会产生与Foo<Bar>(myBar)
不同的语义;在前一种情况下,参数将表现为值类型,在后一种情况下,它将表现为类类型。