http://www.cnblogs.com/shenfx318/archive/2007/01/25/630760.html
C#中的抽象基类(Abstract Class)和接口(Interface)都实现了面向对象中的继承机制,它们通过定义抽象方法匀实现了对继承类的功能上的约束,那么在如何在恰当的场景选择恰当的继承机制是我们在设计中经常会遇到的问题,我们先来对比两者之间的区别与联系。
相同点
都可以被继承。
本身都不能被实例化
不同点
抽象类是一个不完整的类,需要进一步细化;而接口只是一个行为上的规范。
抽象基类不能实现多继承,而接口可以实现多继承。
抽象基类可以定义字段、属性、包含有实现的方法。接口可以定义字段、索引器、事件但不能定义字段和包含实现的方法。
共性、个性与选择
有的书上写到C#中推荐使用接口(Interface)来替代抽象基类(Abstract Class),并强调使用接口的诸多好处,这点我不敢苟同,从上面列表中看来,两者之间还是存在不少差异的,而这种差异的存在性必然决定了适用场景的不同,例如在抽象基类中可以为部分方法提供默认的实现,从而避免在子类中重复实现它们,提高代码的可重用性,这是抽象类的优势所在;而接口中只能包含抽象方法。至于何时使用抽象基类何时使用接口关键还是取决于用户是如何看待继承类之间的联系的,用户更加关心的是它们之间的个性差异还是它们之间的共性联系。举个生活中的例子加以说明。
如果给你三个对象分别是人、鱼、青蛙,让你为他们设计个基类来概括它们之间的联系,那么首先给你的感觉肯定是它们个体间的差异性较大,很难抽象出共性,然而若让你概括他们行为之间的共性,你可能想了想会意识到他们都会游泳,只不过是游泳方式迥异。那么这时你就应当考虑使用接口而不是抽象基类,原因有三条:
个性大于共性。
差异较大的个性间具有某些相同的行为。
相同行为的实现方式有较大区别。
设计为:
interface ISwim
{
void Swim();
}
public class Person : ISwim
{
public void Swim()
{
//Swimming in person's style.
}
}
public class Frog : ISwim
{
public void Swim()
{
//Swimming in frog's style.
}
}
public class Fish : ISwim
{
public void Swim()
{
//Swimming in fish's style.
}
}
好,这时再给你三个对象,分别是鲫鱼、鲤鱼、金鱼,仍然让你设计基类来概括它们之间的联系,那么你第一个意识到的肯定是它们都属于鱼类,其次是他们游泳的方式可能稍有差异,这时就应当使用抽象基类而不是接口,对比着上面的例子,原因也有三条:
共性大于个性
共性相同的个体间必然具有相同的属性与行为。
相同行为的实现方式具有一定区别。
设计为:
abstract public class Fish
{
abstract public void Swim();
}
public class 鲫鱼 : Fish
{
public override void Swim()
{
//Swim like a 鲫鱼
}
}
public class 鲤鱼 : Fish
{
public override void Swim()
{
//Swim like a 鲤鱼
}
}
public class 金鱼 : Fish
{
public override void Swim()
{
//Swim like a 金鱼
}
}
总结:
观察在使用接口或是使用抽象基类的几条理由中,第三条理由其实是一样的,它所描述的是面向对象中多态的概念,即通过覆盖父类的方法来实现,在运行时根据传递的对象引用,来调用相应的方法。第二条理由开始产生分歧,接口更加强调了继承对象间具有相同的行为,而抽象类同时还强调了继承对象间具有相同的属性。而真正将接口与抽象基类区分开的则是理由一,归纳如下:
当在差异较大的对象间寻求功能上的共性时,使用接口。
当在共性较多的对象间寻求功能上的差异时,使用抽象基类。
分享到:
相关推荐
这里我们将详细讨论这些概念以及抽象类与接口之间的相同点和区别。 首先,让我们来看看抽象类(Abstract Class): 1. 抽象方法是只有声明没有实现的方法,可以视为没有方法体的虚方法。例如: ```csharp public ...
(1) 抽象基类可以定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。 (2) 抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。微软的自定义接口总是后带able字段...
1. 抽象基类可以定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。 2. 抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。 3. 接口可以被多重实现,抽象类只能...
1. **目的不同**:抽象类是对一组相关对象的抽象,强调它们之间的共性,而接口更像是一种行为规范,定义了一组必须遵循的操作。 2. **继承限制**:一个类只能直接继承自一个抽象类,但可以实现多个接口。 3. **...
4. **具体与抽象**:抽象类更多地体现了类的内部共性,而接口强调的是类的外部特性。 5. **接口的灵活性**:接口可以被用来支持回调机制,而继承不具备这种特点。 6. **方法的虚与非虚**:抽象类实现的具体方法...
- **使用场景**:当多个类共享一些属性和方法,但又存在差异,这时可以创建一个抽象类作为这些类的基类,提供共性方法的定义。 - **特点**:抽象类可以包含抽象方法(没有方法体的方法)和非抽象方法。包含抽象...
【Java 抽象类与接口的比较】 Java 抽象类和接口是两种重要的抽象机制,它们在面向对象编程中起到关键作用,为程序设计提供了灵活性和可扩展性。虽然两者在某些方面相似,但它们在功能和用法上存在显著差异。 1. *...
【Java 抽象类与接口使用方法】 在Java编程语言中,面向对象的特性之一是继承性,这有助于解决代码复用和结构化设计的问题。当我们创建多个具有相似特性的类,如`Student`和`Employee`时,会发现有很多共享的代码。...
在选择使用接口还是抽象类时,应根据具体需求来决定。接口提供了一种强制约束,确保对象符合特定的行为规范,而抽象类则允许在继承链中提供部分实现,增加灵活性。在实际开发中,常常会结合使用两者,以达到最佳的...
### 深入剖析Java抽象类与接口的神秘力量 - 探索编程世界的双极法则 #### 第一章:抽象类的创世神话 —— 基础与实战 ##### 概念解析: 抽象类在Java编程语言中扮演着极其重要的角色。它可以被视为一种特殊类型的...
与接口不同,一个类只能继承一个抽象类,但可以实现多个接口。抽象类通常作为具有共同特性的类的基类,提供一些通用的方法实现。例如: ```java public abstract class Mammal { public void breathe() { // 具体...
- **代码复用**:抽象基类中可以为部分方法提供默认实现,从而避免子类重复实现,提高代码复用性。 - **简化设计**:通过提供预设的行为,简化了派生类的设计。 **5. 注意事项** - **抽象方法声明**:抽象方法必须...
4. 抽象类往往代表一类事物的共性,而接口更侧重于规定行为的规范。 在使用时,抽象类通常用于定义具有共享属性和行为的类族的公共基类,而接口用于定义一组行为标准,让不同的类遵循相同的契约。在C++中,由于不...
4. **封装和抽象**:通过向基类构造函数传递参数,我们可以将一些共性的初始化逻辑封装在基类中,从而实现代码的抽象和复用。这有助于减少代码重复,提高代码的可维护性。 5. **继承和扩展**:这种设计模式允许我们...
抽象基类通常定义了公共的接口和方法,子类可以继承这些接口和方法来实现自己的逻辑。 5. Abstract Class 抽象类 抽象类是指不能被实例化的类,只能被继承。抽象类通常定义了公共的接口和方法,子类可以继承这些...
方案2引入抽象类,将移动设备的共性抽取到一个抽象基类,提供了一定程度的扩展性。但仍然需要在计算机类中处理每种具体设备的实例。 方案3和4则利用了接口。方案3只使用一个接口,所有设备都实现这个接口,使得...
总的来说,`BaseActivity`和`BaseFragment`的设计体现了Android开发中的最佳实践,通过抽象出共性部分,降低了代码复杂度,提升了开发效率。同时,BaseUtils这样的工具类库也是项目中不可或缺的部分,它们为开发者...
在C#编程中,抽象类和接口是两种重要的抽象机制,它们在实现多态性和代码组织方面起着关键作用。理解它们之间的差异对于编写高效、可维护的代码至关重要。 首先,面向接口编程和面向对象编程的关系并非平行的。面向...
总之,抽象类在Java编程中起到承上启下的作用,它将共性提取出来,为子类提供了一个统一的接口和行为模板。合理使用抽象类能够提升代码的可读性、可维护性和可扩展性,是软件设计中不可或缺的一部分。在Android开发...
例如,一个`Account`类可能作为一个抽象基类,包含一些如`withdrawal`这样的虚函数,但这个类自身不构成有意义的实体,其存在的目的是为不同的子类(如储蓄账户、信用卡账户等)提供共性接口。 【多态性】是C++面向...