java中抽象类和接口的相同和不同点介绍

网友投稿 258 2022-09-08


java中抽象类和接口的相同和不同点介绍

目录前言一、抽象类是什么?二、接口是什么?三、抽象类和接口的异同点总结

前言

本文简单介绍抽象类,接口以及它们的异同点,另附简单的代码举例。

一、抽象类是什么?

在 java 语言中使用 abstract class 来定义抽象类。抽象类是不能被实例化的,即不能用new关键字来实例化对象。包含抽象方法的一定是抽象类,但抽象类不一定包含抽象方法。如果一个子类实现了父类(抽象类)的所有抽象方法,那么该子类可以不必是抽象类,否则就是抽象类。抽象类中的抽象方法的修饰符只能为public或者protected。

为什么要在抽象类中定义抽象方法呢?下面我们来看一个代码实例:

package example;

import java.util.Date;

public abstract class GeometricObject {

private String color="white";

private boolean filled;

private java.util.Date dateCreated;

protected GeometricObject() {

dateCreated=new java.util.Date();

}//构建默认的几何对象

protected GeometricObject(String color,boolean filled) {

dateCreated=new java.util.Date();

this.color=color;

this.filled=filled;

}

public String getColor() {

return color;

}//返回颜色

public void setColor(String color) {

this.color=color;

}//设置新的颜色

public boolean getFilled() {

return filled;

}

public void setFilled(boolean filled) {

this.filled=filled;

}

public java.util.Date getDateCreated(){

return dateCreated;

}

public abstract double getArea();//抽象方法定义得到面积

public abstract double getPerimeter();//抽象方法得到周长

}

我们假设自定义的Circle类和Rectangle类均为GeometricObject的子类,且均有求各自面积的getArea()方法和各自周长的getPerimeter()方法,但这些方法并不能在父类中定义,因为具体的计算方法要取决于几何对象的具体类型。所以采取抽象方法进行定义,这样可以保证父类中的抽象方法可以在子类中被重写。

抽象类只有定义没有实现。

下面是抽象类值得注意的几点:

1.抽象方法不能包含在非抽象类中。如果抽象父类的子类不能实现所有的抽象方法,那么子类也必须定义为抽象的。也就是说,在继承自抽象类的非抽象子类中,必须实现所有的抽象方法。还要注意到,抽象方法是静态的。

2.抽象类不能使用new操作符来初始化。但仍然可以定义它的构造方法,这个构造方法在它的子类的构造方法中进行调用。

3.包含抽象方法的类必须是抽象的。但是是可以定义一个不包含抽象方法的抽象类,这个抽象类用于作为定义新子类的基类。

4.即使子类的父类是具体的,这个子类也可以是抽象的。

5.不能使用new操作符从一个抽象类创建一个实例,但是抽象类可以用做一种数据类型。

例如:GeometricObject[] objects=new GeometricObject[10];是正确的,。

6.子类可以重写父类的方法并将它定义为抽象的,这虽然不常见,但很适用于当父类的方法实现在子类中变得无效时的情况。

二、接口是什么?

接口是一种与类很相似的结构,用于为对象定义共同操作,但它的目的是指明相关或者不相关类的对象的共同行为。

Java中接口使用interface关键字修饰。接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。

类和接口之间的关系称为接口继承。

下面是简单的代码举例:

package example;

public class TestEdible {

public static void main(String[] args) {

// TODO Auto-generated method stub

Object[] objects= {new Tiger(),new Chicken(),new Apple()};

//创建由Tiger,Chicken和Apple类型的三个对象构成的数组

for(int i=0;i

if(objects[i] instanceof Edible)

System.out.println(((Edible)objects[i]).howToEat());

if(objects[i] instanceof Animal) {

System.out.println(((Animal)objects[i]).sound());

}

}//如果可食用,则调用howToEat方法,如果是动物,则调用sound方法

}

}

abstract class Animal{

private double weight;

public double getWeight() {

return weight;

}

public void setWeight(double weight) {

this.weight=weight;

}

public abstract String sound();//返回动物的声音,是抽象方法,被具体的animal类实现

}

class Chicken extends Animal implements Edible{

@Override

public String howToEat() {

return "Chicken: Fry it";

}//实现了Edible接口。当一个类实现接口时,该类实现定义在接口中的所有方法。

@Override

public String sound() {

return "Chicken: cock-a-doodle-doo";

}

}

class Tiger extends Animal{

@Override

public String sound() {

return "Tiger:RROOAARR";

}

}

abstract class Fruit implements Edible{

}//Fruit类实现了Edible,但没有实现howToEat方法,所以它必须定义为abstract。

class Apple extends Fruit{

@Override

public String howToEat() {

return "Apple:Make apple cider";

}

}//Fruit的具体子类必须实现howToEat方法,所以Apple类实现了howToEat方法。

需要注意的是,接口中所有的数据域都是public static final,而且所有方法都是public abstract,但Java允许忽略这些修饰符。

即下面的两个代码是等价的:

public interface T {

public static final int K=1;

public abstract void p();

}

public interface T {

int K=1;

void p();

}

尽管public修饰符对于定义在接口中的方法可以省略,但是在子类实现中方法必须定义为public。

三、抽象类和接口的异同点

一个类可以实现多个接口,但是只能继承一个父类。

首先我们先来列举个表格简单讲述一下抽象类和接口之间的异同点:

比较点

抽象类

接口

关键字

abstract class

interface

字段

无限制

变量必须是public static final

方法

既可以含普通方法,又可以含抽象方法,无限制

只能含抽象方法,且必须是public的

继承/实现

只能被类或抽象类继承

既可以被接口继承,也能被类或抽象类实现

多重继承

不支持

可以继承多个父接口

java只允许为类的继承做单一继承,但是允许使用接口做多重继承。例如:

public class NewClass extends BaseClass implements Interface1,...,InterfaceN{

}

利用extendshttp://,接口可以继承其他接口,这样的接口被称为子接口。例如:下面的代码中,NewInterface是Interface1,...,InterfaceN的子接口。

public interface NewInterface extends Interface1,...,InterfaceN{

}

一个实现NewInterface的类必须实现在NewInterface,Interface1,...,InterfaceN中定义的抽象方法。接口可以继承其他接口但不能继承类。一个类可以继承它的父类同时实现多个接口。

所有的类都有一个共同的根类Object,但是接口并没有共同的根。与类相似,接口同样也可以定义一种类型。一个接口类型的变量可以引用任何实现该接口的类的实例。如果一个类实现了一个接口,那么这个接口就类似于该类的一个父类。可以将接口当作一种数据类型使用,将接口类型的变量转换为它的子类,反过来同样可以。

通常情况下,使用接口的频率更高,因为接口比类更加灵活,不用使所有东西都属于同一个类型的类。

下面进行一个简单的代码举例:

abstract class Animal{

public abstract String howToEat();

}//在Animal中定义howToEat方法

//Animal的两个子类定义如下

class Chicken extends Animal{

@Override

public String howToEat() {

return "Chicken: Fry it";

}

}

class Duck extends Animal{

@Override

public String howToEat() {

return "Roast it";

}

}

public static void main(String[] args) {

Animal animal = new Chicken();

eat(animal);

Animal animal = new Duck();

eat(animal);

}

public static void eat(Animal animal){

System.out.println(animal.howToEat());

}

假设给定这个继承结构,java在调用方法时可以根据对象动态地决定调用具体的howToEat方法。但有一个限制条件,即该子类必须是另一种动物才可以。如果一种动物不可食用,那么此刻再继承Animal类就并不合适了。

限制条件这个问题在接口中可以被解决,例如:

public class Demo{

public static void main(String[] args) {

Edible stuff = new Chicken();

eat(stuff);

Edible stuff = new Broccoli();

eat(stuff);

}

public static void eat(Edible stuff){

System.out.println(stuff.howToEat());

}

}

interface Edible{

public String howToEat();

}

class Chicken implements Edible{

@Override

public String howToEat() {

return "Chicken: Fry it";

}

}

class Broccoli implements Edible{

@Override

public String howToEat() {

return "Broccoli: Stir-fty it";

}

}

定义表示可食用对象的一个类,只须让该类实现Edible接口即可。任何Edible对象都可以被传递以调用HowToEat方法。

总结

if(objects[i] instanceof Edible)

System.out.println(((Edible)objects[i]).howToEat());

if(objects[i] instanceof Animal) {

System.out.println(((Animal)objects[i]).sound());

}

}//如果可食用,则调用howToEat方法,如果是动物,则调用sound方法

}

}

abstract class Animal{

private double weight;

public double getWeight() {

return weight;

}

public void setWeight(double weight) {

this.weight=weight;

}

public abstract String sound();//返回动物的声音,是抽象方法,被具体的animal类实现

}

class Chicken extends Animal implements Edible{

@Override

public String howToEat() {

return "Chicken: Fry it";

}//实现了Edible接口。当一个类实现接口时,该类实现定义在接口中的所有方法。

@Override

public String sound() {

return "Chicken: cock-a-doodle-doo";

}

}

class Tiger extends Animal{

@Override

public String sound() {

return "Tiger:RROOAARR";

}

}

abstract class Fruit implements Edible{

}//Fruit类实现了Edible,但没有实现howToEat方法,所以它必须定义为abstract。

class Apple extends Fruit{

@Override

public String howToEat() {

return "Apple:Make apple cider";

}

}//Fruit的具体子类必须实现howToEat方法,所以Apple类实现了howToEat方法。

需要注意的是,接口中所有的数据域都是public static final,而且所有方法都是public abstract,但Java允许忽略这些修饰符。

即下面的两个代码是等价的:

public interface T {

public static final int K=1;

public abstract void p();

}

public interface T {

int K=1;

void p();

}

尽管public修饰符对于定义在接口中的方法可以省略,但是在子类实现中方法必须定义为public。

三、抽象类和接口的异同点

一个类可以实现多个接口,但是只能继承一个父类。

首先我们先来列举个表格简单讲述一下抽象类和接口之间的异同点:

比较点

抽象类

接口

关键字

abstract class

interface

字段

无限制

变量必须是public static final

方法

既可以含普通方法,又可以含抽象方法,无限制

只能含抽象方法,且必须是public的

继承/实现

只能被类或抽象类继承

既可以被接口继承,也能被类或抽象类实现

多重继承

不支持

可以继承多个父接口

java只允许为类的继承做单一继承,但是允许使用接口做多重继承。例如:

public class NewClass extends BaseClass implements Interface1,...,InterfaceN{

}

利用extendshttp://,接口可以继承其他接口,这样的接口被称为子接口。例如:下面的代码中,NewInterface是Interface1,...,InterfaceN的子接口。

public interface NewInterface extends Interface1,...,InterfaceN{

}

一个实现NewInterface的类必须实现在NewInterface,Interface1,...,InterfaceN中定义的抽象方法。接口可以继承其他接口但不能继承类。一个类可以继承它的父类同时实现多个接口。

所有的类都有一个共同的根类Object,但是接口并没有共同的根。与类相似,接口同样也可以定义一种类型。一个接口类型的变量可以引用任何实现该接口的类的实例。如果一个类实现了一个接口,那么这个接口就类似于该类的一个父类。可以将接口当作一种数据类型使用,将接口类型的变量转换为它的子类,反过来同样可以。

通常情况下,使用接口的频率更高,因为接口比类更加灵活,不用使所有东西都属于同一个类型的类。

下面进行一个简单的代码举例:

abstract class Animal{

public abstract String howToEat();

}//在Animal中定义howToEat方法

//Animal的两个子类定义如下

class Chicken extends Animal{

@Override

public String howToEat() {

return "Chicken: Fry it";

}

}

class Duck extends Animal{

@Override

public String howToEat() {

return "Roast it";

}

}

public static void main(String[] args) {

Animal animal = new Chicken();

eat(animal);

Animal animal = new Duck();

eat(animal);

}

public static void eat(Animal animal){

System.out.println(animal.howToEat());

}

假设给定这个继承结构,java在调用方法时可以根据对象动态地决定调用具体的howToEat方法。但有一个限制条件,即该子类必须是另一种动物才可以。如果一种动物不可食用,那么此刻再继承Animal类就并不合适了。

限制条件这个问题在接口中可以被解决,例如:

public class Demo{

public static void main(String[] args) {

Edible stuff = new Chicken();

eat(stuff);

Edible stuff = new Broccoli();

eat(stuff);

}

public static void eat(Edible stuff){

System.out.println(stuff.howToEat());

}

}

interface Edible{

public String howToEat();

}

class Chicken implements Edible{

@Override

public String howToEat() {

return "Chicken: Fry it";

}

}

class Broccoli implements Edible{

@Override

public String howToEat() {

return "Broccoli: Stir-fty it";

}

}

定义表示可食用对象的一个类,只须让该类实现Edible接口即可。任何Edible对象都可以被传递以调用HowToEat方法。

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:组件分享之后端组件——类似Python的Golang 脚本化运行工具wgo(Python组件)
下一篇:python项目最佳实践(上)`(python基础项目实战)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~