关于abstract class和interface

本文探讨了Java中抽象类和接口的区别与联系,详细解释了二者如何在多重继承、方法实现等方面发挥作用,并通过示例说明了在不同场景下如何选择使用抽象类或接口。
Java的interface和abstract class都可以定义不提供具体实现的方法。其中一个类不能继承自多个abstract class,但是可以实现多个interface。Java的类没有多重继承,所以用interface的概念来补充,通过实现多个interface来实现多重的继承。

在Java中所有的对象都用类来描绘,但是不是每一个类都用来描绘对象的。用来描绘某一类对象共有的本质,这就是抽象。比如:形状存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类(这儿的抽象类并不是abstract class翻译而来的,它包括interface和abstract class)是不能够实例化的。我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。

从语言层面上面来讲:abstract class可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface方式的实现中,只能够有静态的不能被修改的数据成员(也即interface是static final的),所有的成员方法都是abstract的。从这种角度来说,interface是abstarct class的一种特殊情况。abstract class可以提供某些方法的部分实现,而interface不可以,这大概就是abstract class唯一的优点吧,但这个优点非常有用。如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而interface做不到这一点,如果向一个interface里加入一个新方法,所有实现这个接口的类就无法成功通过编译了,因为你必须让每一个类都再实现这个方法才行。

而从设计出发:假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:
abstract class:
[code]abstract class Door{
abstract void open();
abstract void close();
}[/code]
interface:
[code]interface Door{
void open();
void close();
}[/code]
其他具体的Door类型extends absract class或者implements interface就可以了。
看起来好像使用abstract class和interface没有大的区别。

但是现在如果要求Door加上报警的alarm功能,我们应该如何去设计程序的结构呢?
方案一、简单的在abstract class添加abstract void alarm()方法或者在interface中加一个alarm()方法?但是如果这样,在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改alarm方法的参数)而改变。
方案二、既然open()、close()和alarm()是属于两个不同的概念,那么就应该分两个模块来设计。那,这样是应该分成两个abstract class、两个interface还是一个abstract class一个interface呢?
在java中,类是不支持多重继承的,所以,第一种方式不行,第二种方式,用两个interface来描绘:当我们明白AlarmDoor是属于alarm或者door的一种的时候,它会有一个侧重点,用两个相同的interface来描绘,很明显是不能够描绘出来问题的特点的。假设AlarmDoor是属于一个具有报警功能的Door,那么它本质上来说,是一个Door,不过是附加了alarm()的功能而已。所以对于Door的概念我们应该用一个abstract class去描绘,而alarm()的功能则用interface去描绘,代码如下:
[code]abstract class Door{
abstract void open();
abstract void close();
}
interface Alarm{
void alarm();
}
Class AlarmDoor extends Door implements Alarm{
void open(){...}
void close(){...}
void alarm(){...}
}[/code]

BTW:文章借鉴了csdn的jackrong的一篇文章的例子(原文地址已经不知道了),而本身对于abstarct class和interface的理解有一部分也来自这个文章,当是我模仿加抄袭写成的文章吧。初学Java,对概念确实达不到一个高度的认识,只有通过这样的方式,希望今后可以慢慢提高……
### abstract class interface 的区别 #### 1. 定义方式 抽象类(`abstract class`)是一种特殊的类,它允许定义方法签名以及部分实现甚至完全实现的方法。而接口(`interface`)则是一个纯抽象的概念,在某些编程语言中仅能包含方法声明常量字段[^2]。 ```java // 抽象类示例 public abstract class Animal { public abstract void makeSound(); // 抽象方法 public void sleep() { // 抽象方法 System.out.println("Sleeping..."); } } // 接口示例 public interface Movable { void move(); // 默认为公共抽象方法 } ``` #### 2. 方法实现能力 在许多现代编程语言中,如 Java 8 及以上版本,接口可以提供默认方法(`default methods`),从而允许其实现一些逻辑功能。然而,默认情况下,接口中的方法仍然是未被具体化的。相比之下,抽象类可以直接提供完整的实现[^3]。 ```java // 使用默认方法的接口 public interface Flyable { default void fly() { System.out.println("Flying..."); } } // 抽象类中的完整实现 public abstract class Bird { public final void layEggs() { System.out.println("Laying eggs..."); } } ``` #### 3. 多重继承支持 由于一个类只能继承自单一父类,因此如果需要模拟多重继承,则通常会采用接口的方式。多个接口能够同时由同一个类实现,这使得设计更加灵活[^4]。 ```java class Superhero implements Flyable, Movable { @Override public void move() { System.out.println("Moving..."); } @Override public void fly() { System.out.println("Super flying!"); } } ``` #### 4. 成员变量特性 接口不允许存在实例成员变量;它们只可拥有静态最终类型的属性(即常量)。相反地,抽象类既可以有普通的成员变量也可以具备静态或者动态初始化器。 ```java // 正确的接口常量定义 public interface Constants { int MAX_LIMIT = 100; } // 错误尝试给接口添加常量数据成员 public interface WrongExample { String name; // 编译错误:必须显式指定final修饰符并赋初值 } ``` --- ### 使用场景分析 当考虑何时选用 `abstract class` 或者 `interface` 来构建软件组件时,需依据实际需求来决定: - **倾向于使用抽象类的情况** - 当希望共享代码片段的时候; - 如果基类型本身应该具有某种行为表现而纯粹作为模板存在的话; - **更适于选择接口的情形** - 对于那些仅仅关心操作契约而不涉及任何特定算法细节的对象建模过程而言更为合适; - 若要求允许多种不同类型之间形成关联关系以便达成共同目标的情况下尤为适用[^1]。 --- ### 总结表格对比 | 特性 | Abstract Class | Interface | |---------------------|----------------------------------------|---------------------------------------| | 是否可含构造函数 | 是 | 否 | | 能否直接创建对象 | 不可以 | 绝对不可以 | | 支持多继承 | 单一继承 | 支持 | | 提供默认实现 | 可以 | 自 JDK 8 开始可以通过 `default` 关键字实现 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值