java抽象类和接口

java抽象类和接口

面向对象设计过程中重要的一点是如何进行抽象,即把“问题空间”中的元素与“方案空间”中的元素建立理想的一对一的映射关系。抽象类和接口便是抽象过程中的产物。

 

    一、抽象类

    我们知道,对象是通过类来产生的,但是并非所有的类都可以描述具体的对象。

    如果一个类中不包含足够的信息来描述具体的对象,就成为了抽象类。抽象类是对一类有着相同特征,但细节上却有着不同表现的对象的抽象。比如,鸟类都会叫,但是不同的鸟叫法肯定是不同的,可以抽象出“叫”这个概念。

    定义下面一个鸟类:

public abstract class Bird {

    private String color;

 

    public String getColor() {

        return color;

    }

    public void setColor(String color) {

        this.color = color;

    }

    public Bird(){

    }

    public abstract void sing();//鸣叫

}

//喜鹊

class  Magpie extends Bird{

public void sing() {

System.out.println("I can sing in a whisper. ");

}

}

抽象类特征:

(1)抽象类用abstract关键字修饰

(2)抽象类中的抽象方法用abstract关键字修饰,没有方法体(具体实现)。

(3)抽象类可以包含非抽象方法

(4)抽象类可以不包含抽象方法(设计成抽象类就没什么意义了吧。。。),但包含抽象方法的类一定是抽象类

(5)抽象类本质也是类,只能单继承

(6)抽象类不能实例化,不能new。我们前面说过它不描述具体的对象,肯定也不能实例化了

(7)抽象类可以有实例变量和构造方法

 

二、接口

    接口是一组方法特征的集合,是契约,规定了你可以做什么。软件设计过程中要依赖抽象,而非具体实现。

    像我们电脑上的usb接口,无论你是硬盘、u盘、还是手机,只要你实现了usb规定的接口,便能够联通电脑。

    上面抽象类的例子中,我想加入一个“飞”的功能,考虑到并非所有的鸟都会飞,比如:企鹅,鸵鸟,鸭子等等,该怎么办呢?

    修改抽象类肯定是不合适的:1、违反开闭原则,2:会使得所有的子类都继承到“飞”这一功能,我们会看到满天的鸭子在飞了^_^。

    我们可以定义下面一个接口:

public interface IFly {

void fly();

 }

//喜鹊可以实现IBird中的接口:

 

class  Magpie extends Bird implements IFly {

public void sing() {

System.out.println("I can sing in a whisper. ");

}

        public void fly(){

            System.out.println("我会飞了!");

        }

}

    喜鹊实现了IFly中的fly接口,终于可以飞起来了。

    那如果需要给鸟类增加一个游泳的功能呢?自己去想。。。

接口的特征:

    (1)修饰符:public,abstract,default(不写)

    (2)关键字:interface

    (3)接口中的方法都是抽象方法,不可以有实现。

    (4)接口中的方法默认都是public abstract的,实现类中必须使用public修饰。

    (5)接口中的所有方法都必须在实现类(抽象类除外)中实现。

    (6)接口中的变量默认为public static final的。

    (7)一个类可以实现多个接口。

 

    三、应用场景

    1)抽象类体现的是“is a”的关系,如果某一些类的实现有共通之处,则可以抽象出来一个抽象类,让抽象类实现共通的代码,而个性化的方法则由各个子类去实现。 

    2)接口体现的是“like a”的关系,表现的是不同类对象在行为上的抽象。比如飞机和鸟都会飞,可以抽离出飞的接口,但他们非同类。

    3)在软件设计中,当你需要接口与实现分离,封装变化的时候,面向接口编程显得尤为重要。

    比如Ioc思想,客户端不关心你具体是什么类,具体对象由容器来注入。

    再比如两个系统交互,良好的设计是双方提供接口,不关心内部实现,减少耦合性的同时,封装了变化。

    很多设计原则、设计思想以及设计模式都体现出面向接口编程的重要性:开闭原则,接口隔离,依赖倒置,适配器模式等等。


### Java抽象类接口的区别及使用场景 #### 1. 定义上的差异 抽象类是一种部分实现的类,可以包含成员变量、构造函数以及非抽象方法。而接口则完全由常量未实现的方法组成,在Java 8之后允许默认方法(`default methods`)的存在。 在给定的例子中展示了如何定义一个简单的抽象类 `Animal`[^1]: ```java public abstract class Animal { protected String name; public Animal(String name) { this.name = name; } public abstract void makeSound(); } ``` 此代码片段表明抽象类能够拥有字段(如这里的 `name` 字段),构造器,甚至具体的实现方法。然而,接口不允许这些特性直到较新的版本才有所放宽限制[^2]。 #### 2. 继承方式的不同 Java 的类只支持单重继承,这意味着任何类只能有一个直接父类;但是,一个类却能同时实现多个接口。因此当需要模拟多重继承的时候,应该考虑采用接口而非抽象类[^3]。 #### 3. 方法与字段的支持程度对比 - **抽象类**: 可以有带访问修饰符的各种类型的属性(静态/非静态, final/non-final),也可以提供已实现的功能。 - **接口**: 初期仅限于公共静态最终(`public static final`) 常量 抽象方法声明。自 JDK 8 起增加了 default static 方法支持[^4]。 #### 4. 设计理念层面分析 - 如果几个相关的类共享某些行为逻辑,则适合通过抽象类来表达这种关系并提取共同点。 - 当希望规定一组不相干的对象具备某种能力时,比如飞行或者打印文档等功能,此时更倾向于利用接口去描述该契约。 综上所述,选择使用抽象类还是接口取决于具体的应用需求技术背景下的最佳实践考量。 ### 示例代码展示 下面给出一段基于上述理论的实际应用例子: ```java // 定义一个接口 Flyable 表达会飞的能力. interface Flyable { void fly(); } // 创建鸟类作为动物的一种特殊形式,并实现了Flyable接口. class Bird extends Animal implements Flyable { public Bird(String name){ super(name); } @Override public void makeSound() { System.out.println("Chirp chirp"); } @Override public void fly(){ System.out.println(this.name+" is flying."); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值