Java学习-抽象类(abstract)和接口(interface)

1、什么是抽象类

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更为一般,更通用。类的设计应该保证父类和子类能够共享特征,有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。

例如:

Java学习-抽象类(abstract)和接口(interface)_第1张图片

上面动物移动方式没法在动物类中去写,所有动物类和其方法都是抽象化处理,即不写具体的实现

抽象类的特点:

  • 用abstract关键字来修饰类时,这个类叫做抽象类;
  • 含有抽象方法的类必须被声明为抽象类
  • 抽象类代表一种抽象的对象类型
  • 抽象类不能被实例化。抽象类是用来作为父类被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。
  • 抽象类中可以有具体的方法,可以没有抽象方法(也就是说一个类中只要有一个方法是抽象方法那么这个类一定是抽象类,反过来,一个抽象类中可以没有抽象方法,可以带有具体实现的方法)
  • 不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法

抽象方法的特点:

  1. 只有方法头没有方法体的方法称之为抽象方法。(即只有方法的声明,没有方法的实现)
  2. 抽象方法用abstruct关键字来修饰
  3. 抽象方法代表一种不确定的操作或行为。(由子类去具体实现)
  4. 抽象方法不能被调用
package com.zhukun;

abstract class Animal{//定义一个抽象类
	public void action(){//普通方法,存在方法体
		System.out.println("动物的动作");
	}
	public abstract void move();//抽象方法,没有方法体,有abstract关键字做修饰
	
}
//单继承
class Dog extends Animal{//B类是抽象类的子类,是一个普通类
	@Override
	public void move() {//强制要求覆写
		System.out.println("狗的移动方式是跑 !");
	}	
}
public class test {
	public static void main(String[] args)
	{
		Dog d = new Dog();
		d.move();
		d.action();//从父类继承的方法
		Animal a = new Dog();//向上转型
		a.move();//被子类重写过的方法
	}
}
狗的移动方式是跑 !
动物的动作
狗的移动方式是跑 !

可以知道:抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类);

2、抽象类的使用的几个问题

(1)抽象类中有构造方法吗?

         抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。

package com.zhukun;

abstract class Animal{//定义一个抽象类
	public  Animal()
	{
		System.out.println("动物类的构造方法");
	}
	public void action(){//普通方法,存在方法体
		System.out.println("动物的动作");
	}
	public abstract void move();//抽象方法,没有方法体,有abstract关键字做修饰
	
}
//单继承
class Dog extends Animal{//B类是抽象类的子类,是一个普通类
	public  Dog() {
		System.out.println("狗类的构造方法");
	}
	@Override
	public void move() {//强制要求覆写
		System.out.println("狗的移动方式是跑 !");
	}	
}
public class test {
	public static void main(String[] args)
	{
		Dog d = new Dog();//向上转型
	}
}
动物类的构造方法
狗类的构造方法

(2)抽象类可以用final声明吗?

不能,因为抽象类必须有子类,而final定义的类不能有子类;

(3)抽象类能否使用static声明?

外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。使用static声明的内部抽象类相当于一个外部抽象类,继承时使用“外部类.内部类”的形式表示类名称

package com.zhukun;

abstract class Animal{//定义一个抽象类
	static abstract class Action{
		public abstract void move();//抽象方法,没有方法体,有abstract关键字做修饰
	}
}
//单继承
class Dog extends Animal.Action{//B类是抽象类的子类,是一个普通类
	public void move() {//强制要求覆写
		System.out.println("狗的移动方式是跑 !");
	}	
}
public class test {
	public static void main(String[] args)
	{
		Animal.Action ab = new Dog();//向上转型
		ab.move();
	}
}
狗的移动方式是跑 !

(4)可以直接调用抽象类中用static声明的方法吗?

任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。

(5)有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。

package com.zhukun;

abstract class A{//定义一个抽象类
	public abstract void print();	
	private static class B extends A{//内部抽象类子类		
		public void print(){//覆写抽象类的方法
			System.out.println("Hello World !");
		}
	}
	//这个方法不受实例化对象的控制
	public static A getInstance(){
		return new B();
	}
}
public class test
{
	public static void main(String[] args) {
				//此时取得抽象类对象的时候完全不需要知道B类这个子类的存在
		A a = A.getInstance();
		a.print();
	}
}

3、接口

3.1接口的介绍

  • 接口(interface)是抽象方法和常量值的定义的集合
  • 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现
  • 一个类可以实现多个接口,接口也可以继承其他接口
  • 接口没有构造器

3.2为什么要用接口?

  1. 接口被用来描述一种抽象
  2. 有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果
  3. 接口也被用来实现解耦

3.3接口的语法实现

声明一个接口,我们使用interface关键字。在接口中的所有方法都必须只声明方法标识,而不要去声明具体的方法体,因为具体的方法体的实现是由继承该接口的类来去实现的,因此,接口并不用管具体的实现。接口中的属性默认为Public Static Final.接口中的所有方法都默认是由public abstruct修饰。

实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化。否则,仍为抽象类。接口的主要用途就是被实现类实现。与继承关系类似,接口与现实类之间存在多态性

(接口采用多层继承机制:接口可以继承接口)

interface in1
{
	final int a = 10;
	void display();
}

为了实现这个接口,我们使用implements关键词去实现接口:

class Outtest implements in1
{
	public void display()
	{
		System.out.println("我是:"+a);
	}
}

测试

public class test
{
	public static void main(String[] args) {
		Outtest o = new Outtest();
		o.display();
	}
}
我是:10

如果一个类既继承父类,又实现接口。那么先继承后实现。

package com.zhukun;

interface in1
{
	final int a = 10;
	void display();
}
class A{
	private int a = 20;
	public A()
	{
		System.out.println("A类构造器");
	}
	public void display()
	{
		System.out.println("我是:"+a);
	}
}
class Outtest extends A implements in1
{
	public void display()
	{
		System.out.println("我是:"+a);//可以用接口中的a,父类中的a为private,没有继承
	}
}
public class test
{
	public static void main(String[] args) {
		Outtest o = new Outtest();
		o.display();
		A a = new A();
		a.display();
	}
}
A类构造器
我是:10
A类构造器
我是:20

4、接口和抽象类的区别

问题:接口和抽象类很相似,好像接口能做的事用抽象类也能做,干嘛还要用接口呢?

我们发现:一个父类为抽象类,当父类增加新的抽象方法时。子类必须实现父类新增加的抽象的方法,否则就得把子类改为抽象类,这样不可行。

实际解决:如果父类要新增一个抽象方法,新建一个接口,把父类需要新增的抽象方法放到接口里面,如果子类需要实现这个新增的方法直接实现这个接口就好了

(父类需要的是稳定的抽象,有时我们又确实需要给父类增加一些方法,那么就不能直接在父类上下手,只能新建一个接口,在接口上扩展方法,其他需要的子类自行去实现接口)

Java学习-抽象类(abstract)和接口(interface)_第2张图片

(如图:需要用Java描述会唱歌的厨子是个老师,因为Java语言不支持多继承所以只能一个个继承过去,像图中上半部分的结构一样,可以发现这样会污染cook类,cook和singer实际中没什么关系,cook却继承了singer。所以正确的做法时teacher类直接继承person类,同时实现cooking接口和sing接口)

你可能感兴趣的:(java学习,java,抽象类,接口)