Java的抽象类与接口使用

Java的抽象类与接口

一、抽象类
在了解抽象类之前,先来了解一下抽象方法。抽象方法是一种只有声明,而没有具体的实现的特殊的方法。抽象方法的声明格式为:

abstract void Quanta();

抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。但是它的子类可以创建对象

Public abstract class Quanta {
	abstract void fun();
}

我们都知道,父类是将子类所共同拥有的属性和方法进行抽取,这些属性和方法中,有的是已经明确实现了的,有的还无法确定,那么我们就可以将其定义成抽象,在后面的子类进行重用,进行具体化。这样,抽象类也就诞生了。

例如,定义了“动物”父类,其中“动物名称”和“动物年龄”属性已经明确了,但是“动物叫”的方法没有明确,此时就可以将“动物叫”定义为抽象方法。

包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。注意,抽象类要注意这几点:

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

  4. 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。

  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

  6. 外部抽象类不能用final、static声明。

示例:

package Course;

abstract class Student{
	//私人变量
	private String name;
	private int age;
	
	//构造方法
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public void print1() {
		System.out.println(name);
	}
	
	public abstract void print2();
}

public class abstractTest {
}

如果我们在public class abstractTest {}中尝试实例化,系统就会报错:
可以看到报错信息
我们可以采用另外一种办法来实例化它:
我们创建一个NewStudent类extends我们的抽象类,再实例化NewStudent

package Course;

abstract class Student{
	//私人变量
	private String name;
	private int age;
	
	//构造方法
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public void print1() {
		System.out.println(name);
	}
	
	public abstract void print2();
}

class NewStudent extends Student{

	public NewStudent(String name, int age) {
		super(name, age);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void print2() {
		// TODO Auto-generated method stub
		System.out.println("继承了");
	}
	
}

public class abstractTest {
	public static void main(String[] args) {
		Student student = new NewStudent("quanta", 0);
	}
}

注意:在父类中定义的抽象方法,在子类中必须实现(即方法重写)如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

二、接口
接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到Java语言设计者的初衷,它是对行为的抽象。在Java中,定一个接口的形式如下:

[public] interface InterfaceName {
 
}

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口的使用
由于接口里面存在抽象方法,所以接口对象不能直接使用关键字new进行实例化。接口的使用原则如下:
(1)接口必须要有子类,但此时一个子类可以使用implements关键字实现多个接口;
(2)接口的子类(如果不是抽象类),那么必须要覆写接口中的全部抽象方法;
(3)接口的对象可以利用子类对象的向上转型进行实例化。

接口特性

  1. 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
  2. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
  3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
  4. 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。

简单一例:

package Course;

//定义一个接口A
interface A {
	public static final String a = "Quanta";//一个全局变量
	
	public abstract void print();//定义一个抽象方法
}

interface B{
	public abstract void get();
}

class Test1 implements A{

	@Override
	public void print() {
		// TODO Auto-generated method stub
		
	}
}

class Test2 implements A,B{

	@Override
	public void get() {
		// TODO Auto-generated method stub
		System.out.println("Quanta");
		
	}

	@Override
	public void print() {
		// TODO Auto-generated method stub
		System.out.println("Hello Quanta");
	}
	
}

public class InterfaceTest {
	public static void main(String[] args) {
		Test2 test2 = new Test2();//实例化子类对象
		A a = test2;
		B b = test2;//向上转型
		
		a.print();
		b.get();
	}
}

我们再来看看如果这样:

public class InterfaceTest {
	public static void main(String[] args) {
		Test2 test2 = new Test2();//实例化子类对象
		A a = test2;
//		B b = test2;//向上转型
		B b = (B)a;
		
		a.print();
		b.get();
		
		System.out.println(a instanceof A);
		System.out.println(b instanceof B);
	}
}

结果是:

Hello Quanta
Quanta
true
true

接口的继承
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。

下面的Sports接口被Hockey和Football接口继承:

// 文件名: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}
 
// 文件名: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}
 
// 文件名: Hockey.java
public interface Hockey extends Sports
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}

Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。

相似的,实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。

接口的多继承
在Java中,类的多继承是不合法,但接口允许多继承。

在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:

public interface Hockey extends Sports, Event

标记接口
最常用的继承接口是没有包含任何方法的接口。

标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。

标记接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。

例如:java.awt.event 包中的 MouseListener 接口继承的 java.util.EventListener 接口定义如下:
package java.util;
public interface EventListener
{}

没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:

建立一个公共的父接口:
正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。

向一个类添加数据类型:
这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。

猜你喜欢

转载自blog.csdn.net/CacheU/article/details/83144568