抽象类和接口以及它们的区别

抽象类与接口

##本博客讲述了抽象类和接口以及它们的区别。每一个知识点之后都有相应的代码演示。欢迎大家进行补充##

1. 抽象类

在Java中所有的对象都是通过类来描绘的,但是,并不是所有的类都是用来描绘对象的,
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

当发现多个类中有共有的方法时,可以将他们抽象出来,例如,狗和狼都会叫这一行为,而且它们都
属于犬科类,所以将这一行为抽象出来,定义犬科为抽象类。狗和狼均继承犬科类,并覆盖其方法。
在子类中具体实现。

具体实现代码1:

package 抽象类;
abstract class 犬科{
	abstract void 叫();//抽象函数,需要用abstract修饰,用分号结束。
}
class Dog extends 犬科{
	void 叫(){
		System.out.println("汪汪汪 ");
	}
}

class Wolf extends 犬科{
	void 叫(){
		System.out.println("吼吼吼");
	}
}

public class AbstractDemo1 {
public static void main(String[] args) {
	Dog dog = new Dog();
	dog.叫();
	Wolf wolf = new Wolf();
	wolf.叫();
}
}

具体实现2:

`public abstract class Animal {
  	public abstract void cry();
}

public class Cat extends Animal{
@Override
public void cry() {
    System.out.println("猫叫:喵喵...");
	 }
}

public class Dog extends Animal{

@Override
public void cry() {
    System.out.println("狗叫:汪汪...");
}
}

public class Test {
 public static void main(String[] args) {
    Animal a1 = new Cat();
    Animal a2 = new Dog()
    a1.cry();
    a2.cry();
}
}`
注意:
1. 抽象类和抽象方法必须由abstract关键字指定。抽象方法一定要定义在抽象类中。
2. 抽象类不可以创建实例(即不能new对象)
		原因:调用抽象方法没有意义。所以抽象类必须被继承。
3. 只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。否则该子类还是一个抽象类。
4. 任何子类必须重写父类中的所有抽象方法,否则声明自身为抽象类。
细节:
1.抽象类一定是一个父类?
	是的,因为抽象类是不断抽取而来的。
2.抽象类是否有构造方法?
	有,虽然抽象类不能给自己的对象初始化,但是可以给自己的子类对象初始化,
3.抽象类和一般类的异同点:
	相同:
		1.都是用来描述事物的。
		2.它们之中都可以定义属性和行为。
	不同:
		1.一般类可以具体的描述事物;抽象类描述事物的信息不具体。
		2.抽象类中可以多定义一个成员:抽象函数。
		3.一般类可以创建对象,而抽象类不能创建对象。
3.抽象类中是否可以不定义抽象方法?
	可以的,此时的意义仅仅是不让该类创建对象。	
4.抽象关键字abstract不可以和哪些关键字共存?
	1)final 修饰的类不能有子类,而抽象类必须有子类。
	2)private 私有的,也不能被覆盖
	3)static 静态方法随着类的加载而加载。
案例分析:
`package 抽象类;
/*
 *需求:公司中程序员有姓名,工号,薪水,工作内容
 *	项目经理除了有姓名,工号。薪水。还有奖金,工作内容, 
 *
 *分析:
 *	程序员
 *		属性:姓名 工号 薪水
 *		行为:工作(code...)
 *  经理: 
 *  	属性: 姓名 工号 薪水 奖金
 *   	行为: 工作(manage...)
 *   
 * 所以 抽象类为员工Employee
 *  
 */
//员工抽象类
abstract class Employee{
private String name;
private int id;
private double pay;
public Employee(String name,int id,double pay){
	this.name = name;
	this.id = id;
	this.pay = pay;
}

@Override
public String toString() {
	return "Employee [name=" + name + ", id=" + id + ", pay=" + pay + "]";
}

abstract void work();
}
//程序员
class Programmer extends Employee{

public Programmer(String name, int id, double pay) {
	super(name, id, pay);//调用父类的构造方法
}
void work(){
	System.out.println("code....");
}

}

class Manager extends Employee{
  	private double award;
	public Manager(String name, int id, double pay,double award) {
	super(name, id, pay);
	this.award = award;
}

void work(){
	System.out.println("manage...");
}
}

public class AbstractDemo2 {
public static void main(String[] args) {
	Programmer programmer = new Programmer("小曾", 2, 10000);
	System.out.println(programmer);
	programmer.work();
}
}`

2. 接口

当一个抽象类中的方法全是抽象的时候,此时用另一种特殊的形式体现。用interface关键字定义
接口是用来建立类与类之间的协议,它所提供的只是一种形式,而没有具体的实现。
接口是抽象类的延伸
接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
interface Animal {
	public void eat();
	public void travel();
}
接口的特点
1.接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类
2.子类必须覆盖接口中所有的抽象方法后,子类才可以实例化。
3.接口中不存在具体的实现的方法
4.接口没有构造方法。
5.接口中所有的方法必须是抽象方法。
6.变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称为常量
7.方法必须有固定的修饰符,public abstract ,所以接口中的成员都是公共的。
8.接口支持多继承。
具体代码1:
`package 接口;

/*
 * 定义一个接口,接口中可以有成员变量和方法
 * 注意:
 * 	变量:变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称为常量
 *  方法:方法必须有固定的修饰符,public abstract ,所以接口中的成员都是公共的。
 */
interface Demo{
public static final int NUM = 6;
public abstract void show1();
public abstract void show2();

/*
 * 也可以写成此类型
 * int NUM = 6;
 * void show1();
 * void show2();
 */
}

//类实现接口,并重写接口中的方法
public class DemoImpl implements Demo{
	@Override
public void show1() {
	
}
@Override
public void show2() {
	
}

}`
具体代码2:
class D{
	public void show(){};
interface A{
	void show();
}
interface B{
	void show();
}
class C extends D implements A,B{
	public void show(){
	}
}
接口的好处:
接口中的方法都没有方法体,由子类来明确。接口可以多实现。
接口的出现避免了单继承的局限性;
父类中定义的事物的基本功能;接口中定义事物的扩展功能。
接口与接口是多继承
在Java中,类的多继承是不合法,但接口允许多继承。
在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 
代码演示
interface interA{
	void show1();
}
interface interAA{
	void show11();
}
interface interB extends interA,interAA{//接口实现多继承
	void show2();
}

class Test implements interB{

@Override
public void show1() {}

@Override
public void show11() {}

@Override
public void show2() {}
}
没有抽象方法的抽象类:抽象类中可以不定义抽象方法,原因仅是不让该类创建对象。

代码过程:
1.定义接口Inter(其中有四个抽象方法),类InterImpl1,InterImpl2 分别实现Inter接口,

`interface Inter{
//定义四种显示功能
public void show1();
public void show2();
public void show3();
public void show4();
}

//定义一个类,要使用显示第一种显示方法
class InterImpl1 implements Inter{

@Override
public void show1() {
	System.out.println("显示第一种方式");
}
//为了让该类实例化,还需要覆盖其他三个方法,
public void show2(){}
public void show3(){}
public void show4(){}
}
class InterImpl2 implements Inter{
@Override
public void show3() {
	System.out.println("显示第三种方式");
}
//为了让该类实例化,还需要覆盖其他三个方法,
public void show2(){}
public void show1(){}
public void show4(){}
}

为了使用接口中的部分方法,而覆盖了全部的方法,而且每一个子类都要这么做,复用性差。
所以
将这些不同的方法都单独抽取到一个独立的类中,让这个类去实现接口,并覆盖接口中所有的方法。

`abstract class InterDemoImpl implements Inter{   
//重写接口中所有的方法
@Override
public void show1() {
}

@Override
public void show2() {
}

@Override
public void show3() {
	
}

@Override
public void show4() {
}

}`

class InterImpl1 extends InterDemoImpl{
public void show1(){
	System.out.println("显示第一个方法");
}
}	

class InterImpl2 extends InterDemoImpl{
public void show3(){
	System.out.println("显示第三个方法");
}
}


public class DemoImpll1 {
public static void main(String[] args) {
 InterImpl1 impl1 = new InterImpl1();
 impl1.show1();
 InterImpl2 impl2 = new InterImpl2();
 impl2.show3();
}
}
这个类并不知道具体的实现内容,都是空实现,不需要将此类创建对象,所以对其抽象化。
接口的设计思想
1.接口的出现对功能实现了扩展。
2.接口的出现定义了规则
3.接口的出现降低了耦合性。
接口和抽象类的区别

事件描述:
犬:假如按照功能分类:导盲犬,缉毒犬。。。
行为:
吼叫();
吃饭();

abstract class 犬{
public abstract void 吼叫();
public abstract void 吃饭();
}



abstract class 缉毒{

public abstract void 缉毒();
}

class 缉毒犬 extends 犬{

@Override
public void 吼叫() {
}
@Override
public void 吃饭() {
}
public void 缉毒(){
	
}
}
//其他的动物可能也会有缉毒功能,无法实现多继承,当犬是接口,缉毒也是接口时,可以多实现。但是类负责描述的是事物的基本功能,接口负责描述事物的扩展功能。所以,犬可以描述为类,缉毒可以描述为接口。
 	
所以 以上代码改为:
abstract class 犬{
	public abstract void 吼叫();
	public abstract void 吃饭();
}

interface  缉毒{
	public abstract void 缉毒();
}
class 缉毒犬 extends 犬  implements 缉毒{
@Override
public void 吼叫() { }
@Override
public void 吃饭() { }
public void 缉毒(){ }
}

抽象类与接口的区别:

1.抽象类是描述事物的基本功能,可以定义非抽象的方法;接口中的定义的方法是抽象的。
2.类与类之间是继承关系,类与接口是实现关系。
3.抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
4.抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
5.接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
6.一个类只能继承一个抽象类,而一个类却可以实现多个接口。

扩展

对于抽象类而言,它是自下而上来设计的,我们要先知道子类才能抽象出父类,而接口则不同,它根
本就不需要知道子类的存在,只需要定义一个规则即可,至于什么子类、什么时候怎么实现它一概不
知。比如我们只有一个猫类在这里,如果你这是就抽象成一个动物类,是不是设计有点儿过度?我们
起码要有两个动物类,猫、狗在这里,我们在抽象他们的共同点形成动物抽象类吧!所以说抽象类往
往都是通过重构而来的!但是接口就不同,比如说飞,我们根本就不知道会有什么东西来实现这个飞
接口,怎么实现也不得而知,我们要做的就是事前定义好飞的行为接口。所以说抽象类是自底向上抽
象而来的,接口是自顶向下设计出来的。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小曾同学.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值