共计 3943 个字符,预计需要花费 10 分钟才能阅读完成。
相干文章:
- 《面向对象再探索》:介绍了面向对象的基本概念
- 《详解 Java 的对象创立》:介绍了对象的创立、结构器的应用
- 《一文打尽 Java 继承的相干问题》:介绍了继承的应用形式和注意事项
本文来介绍 Java 的抽象类和接口的应用。
1. 抽象类
在后面的文章中提到过:父类比子类更加形象,子类比父类更加具体。
在《一文打尽 Java 继承的相干问题》这篇文章中举了动物和狗的例子:
public class Animal {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public Animal() {}
public void say() {System.out.println("我是" + name + ",往年" + age + "岁了");
}
//getters and setters ...
}
public class Dog extends Animal {
private String address;
public Dog(String name, int age, String address) {super(name, age);
this.address = address;
}
public Dog() {}
public void say() {System.out.println("我叫" + super.getName() + ",往年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
}
public void watchDoor() {System.out.println("我在" + address +"看门...");
}
//getters and setters ...
}
下面 Dog
类很天然地继承了 Animal
类,没故障!然而认真推敲一下 Animal
类的 say()
办法。
动物是一个很宽泛的概念,如果写代码示意,咱们平时见到的大部分生物都能够继承该类。如下图:
有这么多类继承 Animal
类,那 Animal
类的 say()
办法这样写适合吗?因为每种动物谈话的形式都不同,而动物又是这么宽泛的一个概念,咱们通常会 new Dog()
或new People()
,但很少会去new Animal()
。
所以 Animal
类的 say()
办法体对其来说就是鸡肋个别的存在,因为即便有办法体,也会被其子类重写。既然这样那就罗唆不要办法体了。
换句话说,咱们将 Animal
类再进行更高层次地形象,它具备各种动物都有的属性,比方 name
、age
,也有各种动物都有的行为,比方say
。 然而,Animal
类并不具体实现该办法,具体的实现交给子类来做。
这样一来,谁继承了 Animal
类,谁就有了它的属性和行为,子类不必管父类的行为是否适合,因为父类的行为“有名无实”,所以子类只需继承这些“名”,具体的“实”则由子类来实现。
这样的 Animal
类就是 抽象类。
上面将上例中的 Animal
类批改为抽象类,Dog
类无需改变:
public abstract class Animal {
private String name;
private int age;
public Animal(String name, int age) {// 有参结构器
this.name = name;
this.age = age;
}
public Animal() {// 无参结构器}
public abstract void say();// 形象办法
public String getName() {// 被具体实现的办法
return name;
}
public void setName(String name) {this.name = name;}
//getters and setters..
}
上面是抽象类的特点:
(一)抽象类被 abstract
关键字润饰。
public abstract class Animal {//......}
(二)类中没有办法体的办法叫 形象办法 ,也须要应用abstract
关键字润饰。
public abstract void say();// 形象办法
(三)有形象办法的类肯定是抽象类。
(四)没有形象办法的类也能够是抽象类。
(五)抽象类中能够有成员变量、结构器、被具体实现的办法。结构器不能是形象的。
(六)抽象类不能被实例化,然而能够申明一个抽象类变量
Animal animal = new Animal();// 报错: 'Animal' is abstract; cannot be instantiated
Anima animal;// 抽象类变量,可行
咱们以前遇到的类,比方 Dog
类,是用来形容对象的,但抽象类的办法没有具体实现,所以它没有足够的信息来形容对象,所以抽象类只能被继承用来形容其子类而不能实例化。
(七)子类扩大形象父类有两种抉择:
- 当子类不是抽象类时,子类必须实现形象父类的形象办法:
public class Dog extends Animal {
// 属性、结构器、其余办法
// 实现形象父类的形象办法
@Override
public void say() {System.out.println("我叫" + super.getName() + ",往年" + super.getAge() + "岁了,家住" + address + ",汪汪汪...");
}
}
- 当子类是抽象类时,子类能够实现形象父类的形象办法,也能够抉择不实现。
public abstract class Dog extends Animal {
// 属性、结构器、其余办法
// 能够抉择不实现父类的形象办法
}
2. 接口
2.1. 什么是接口?
生存中有一种接口是大家每天都在用的,那就是插座。
不论是什么样的电器,冰箱、电视、电脑、电风扇,只有买回来,就能插上通电。之所以这么便当,就是因为电器生产商和插座生产商都恪守了一个 生产标准:我把插座生产成这个模样,你把插头也生产成这个模样,我不论你电器外部是啥样,你也不必管我的插座外部是啥样,大家把产品生产好,各自卖给客户,合作愉快,一起赚钱。这些产品如果当前坏了,那就再买一个恪守标准的就能持续配套应用了。
想一想,如果没有这个标准,插座和插头生产的千奇百怪,买回来怎么用?只能把插座和冰箱拆开,用手接 220V 的电线了。
换句话说,接口就是生产标准 / 规范,或者单方恪守的协定,只有单方都恪守,那么就能欢快地交换、欢快地单干。
在 Java 开发中,一个软件系统必定不是由一个人实现的,而是由一个团队实现的。那如何防止甲写的类乙不能用,乙写的类丙不能用呢,最初导致甲改了乙的代码,乙改了丙的代码?当时定好标准(接口),大家都恪守接口,只有我晓得你的接口,那么我不须要晓得你的具体代码,就能调用你的类。
2.2. 接口的应用
把握对于接口几个特点就能欢快地写接口了:
(一)Java 中应用 inteface
关键字来申明一个接口,接口必须是 public
的,只有私有了能力让大家恪守:
public interface Runnable {}
(二)接口中通常写各种形象办法,但只申明,不能写办法体。
public interface Runnable {/*public abstract*/ void run();
}
(三)不用将办法申明为 public abstract
,在接口中的所有办法都默认的是public abstract
润饰。
(四)接口中不能有成员变量、动态代码块。
(五)接口中能够含有常量,常量默认是 public static final
润饰。
public interface Runnable {
/*public static final*/ int i = 1;
void run();}
(六)类通过 implements
关键字 实现接口,必须同时实现接口中的所有办法。
public class Dog implements Runnable {
@Override
public void run() {System.out.println("跑得飞快");
}
//......
}
(七)如果实现接口的类是抽象类,能够不必实现接口中的办法。
(八)一个类能够同时继承类和实现接口。
public class Dog extends Animal implements Runnable {//......}
(九)一个类能够实现多个接口。
public class Dog implements Runnable, Flyable {//......}
(十)接口之间能够继承,并且容许多继承。
public interface A {//......}
public interface B extends A, Runnable{//......}
(十一)接口不能被实例化,然而能够申明一个接口变量。
Runnable runnable = new Runnable();//'Runnable' is abstract; cannot be instantiated
Runnable runnable;// 接口变量,可行
3. 总结
抽象类用 abstract
关键字申明,抽象类中除了能够有形象办法(用 abstract
关键字申明)外,还能够有一般类的成员变量、结构器、办法。不能被实例化,但能够申明抽象类的变量。子类继承抽象类要实现父类的形象办法(如果子类是形象的,则不必实现)。
接口用 interface
关键字申明,接口中只能有形象办法、常量(疏忽修饰符)。不能被实例化,但能够申明接口变量。接口之间能够继承,且容许多继承。类实现接口应用 implements
关键字,且必须实现接口中的形象办法(如果类是形象的,则不必实现)。
总结了抽象类和接口的特点,发现抽象类如同也能作为“接口”应用。那有了抽象类,为什么还要有接口?
类只能单继承,如果应用抽象类作为“接口”,这意味着一个类只能恪守一份“接口”,显然不符合实际。而接口则灵便多了。
4. 对于我
如有谬误,还请斧正。