Java基本功練習十九(抽象類和接口【抽象類、接口(監聽器、克隆、可比較)、包裝類、有理數類實現】)

在展示範例之前,先介紹一些相關的概念和注意點,這是抽象類和接口的基礎預備知識。

在繼承的層次結構中,隨着每個新子類的出現,類會變的越來越明確和具體。如果從一個子類追溯到父類,類就會變得更通用、更加不明確。類的設計應該確保父類包含子類的共同特徵。

有時候,一個父類設計的非常抽象,以至於它沒有任何具體的實例。這樣的類稱爲抽象類

抽象類中不實現,只聲明的方法稱爲抽象方法。在方法頭中用abstract修飾符表示。在類頭使用abstract修飾符表示該類爲抽象類。在UML類圖中,抽象類和方法的名字用斜體表示。

抽象類和常規類很像,但是不能使用new操作符創建它的實例。抽象方法只有定義而沒有實現。它的實現由子類提供。一個包含抽象方法的類必須聲明爲抽象類。

抽象類的構造方法定義爲protected,因爲它只被子類使用。創建一個具體子類的實例時,它的父類構造方法被調用以初始化父類中定義的數據域。

關於抽象類的幾個注意點:

1)抽象方法不能包含在非抽象類中。如果抽象父類的子類不能實現所有的抽象方法,那麼子類必須定義爲抽象的。換句話說,在抽象類擴展的非抽象類中,必須實現所有的抽象方法。並且,抽象方法是非靜態的。

2)包含抽象對象的類必須是抽象的。但是,可以定義一個不包含抽象方法的抽象類。在這種情況下,不能使用new操作符創建該類的實例。這種類是用來定義新子類的基類的。

3)即使子類的父類是具體的,這個子類也可以是抽象的。

4)子類可以覆蓋父類的方法並將它定義爲abstract。這是很少見的,但是它在當父類的方法實現在子類中變得不合法時是很有用的。在這種情況下,子類必須定義爲abstract。

5)不能使用new操作符從一個抽象類創建一個實例,但是抽象類可以用作一種數據類型。

接口是一種與類相似的結構,只包含常量和抽象方法。它在很多方面都與抽象類很相似,但是它的目的是指明多個對象的共同行爲。如,使用正確的接口,可以指明這些對象是可以比較的、可食用的或可克隆的。

Java中,接口被看作是一種特殊的類。就像常規類一樣,每個接口都被編譯爲獨立的字節碼文件。與抽象類相似,不能使用new操作符創建接口的實例,但是大多數情況下,使用接口或多或少有點像使用抽象類。如可以使用接口作爲引用變量的數據類型或類型轉換的結果等等。

接口和抽象類的區別

或多或少可以使用和抽象類一樣的方式使用接口,但是定義一個接口和定義一個抽象類有所不同,如下表所示:


  Java只允許爲類的擴展做單一繼承,但是允許使用接口做多重擴展,如下所示的定義是合法的。

接口可以擴展其他接口而不是類。一個類可以擴展它的父類同時實現多個接口 。

所有的類共享同一個根類Object,但是接口沒有共同的根。與類類似,接口也可以定義一種類型。一個接口類型的變量可以引用任何實現該接口的類的實例。如果一個類實現了一個接口,那麼這個接口就類似於該類的一個父類。可以將接口當作一種數據類型使用,將接口類型的變量轉換成他的子類,反過來也可以。


範例一:抽象類的使用範例。

運行效果如圖:

實現的源代碼如下所示:

package Blog;

public class blogTryProject {
	public static void main(String[] args) {
		TestChouXiang tcx = new TestChouXiang();
		tcx.main(args);
	}
}
//抽象類測試程序
class TestChouXiang{
	public static void main(String[]args){
		Rectangle rt = new Rectangle(4,5);
		System.out.println(rt.toString());
		System.out.println("Rectangle 的面積爲:"+rt.getArea());
		System.out.println("Rectangle 的周長爲:"+rt.getPerimeter());
		
		Circle c = new Circle(3);
		System.out.println(c.toString());
		System.out.println("Circle 的面積爲:"+c.getArea());
		System.out.println("Circle 的周長爲:"+c.getPerimeter());
	}
}
//抽象類GeometricObject
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 void setFilled(boolean filled){
		this.filled = filled;
	}
	public java.util.Date getDateCreated(){
		return dateCreated;
	}
	public String toString(){
		return "created on "+dateCreated+"\ncolor: "+color+"\t\tfilled: "+filled;
	}
	public abstract double getArea();
	public abstract double getPerimeter();
}
//矩形類
class Rectangle extends GeometricObject{
	private double width;
	private double height;
	public Rectangle(){
	}
	public Rectangle(double width,double height){
		this.width = width;
		this.height = height;
	}
	public Rectangle(double width,double height,String color,boolean filled){
		this.width = width;
		this.height = height;
		setColor(color);
		setFilled(filled);
	}
	public double getWidth(){
		return width;
	}
	public void setWidth(double width){
		this.width = width;
	}
	
	public double getHeight(){
		return height;
	}
	public void setHeight(double height){
		this.height = height;
	}
	
	public double getArea(){
		return width * height;
	}
	
	public double getPerimeter(){
		return 2 * (width + height);
	}
	public String toString(){
		return super.toString()+"\n寬爲:"+getWidth()+"\t\t長爲:"+getHeight();
	}
}
//圓類
class Circle extends GeometricObject{
	private double radius;
	public Circle(){
	}
	public Circle(double radius){
		this.radius = radius;
	}
	
	public Circle(double radius,String color,boolean filled){
		this.radius = radius;
		setColor(color);//這裏不能用this.color = color;因爲它是父類的私有數據域,在GeometricObject
		//類外只能通過訪問器和修改器對它進行操作
		setFilled(filled);
	}
	public double getRadius(){
		return radius;
	}
	public void setRadius(double radius){
		this.radius = radius;
	}
	public double getArea(){
		return radius * radius * Math.PI;
	}
	public double getPerimeter() {
		return 2 * radius * Math.PI;
	}
	public double getDiameter(){
		return 2 * radius;
	}
	public String toString(){
		return super.toString()+"\n半徑爲: "+radius;
	}
}

範例二:接口的簡單範例。

運行效果如圖所示:

實現的源代碼如下所示:

package Blog;

public class blogTryProject {
	public static void main(String[] args) {
		TestEdible te = new TestEdible();
		te.main(args);
	}
}
//接口的簡單範例
interface Edible{
	public abstract String howToEat();
}
class TestEdible{
	public static void main(String[]args){
		Object[] objects = {new Tiger(),new Chicken(),new Apple(),new Orange()};
		for(int i = 0;i < objects.length;i++)
			if(objects[i] instanceof Edible)
				System.out.println(((Edible)objects[i]).howToEat());
	}
}
class Animal{
}
class Chicken extends Animal implements Edible{
	public String howToEat(){
		return "Chicken: Fry it";
	}
}
class Tiger extends Animal{
}
abstract class Fruit implements Edible{
}
class Apple extends Fruit{
	public String howToEat(){
		return "Apple: Make apple cider";
	}
}
class Orange extends Fruit{
	public String howToEat(){
		return "Orange: Make orange juice";
	}
}

範例三:監聽器接口(ActionListener),克隆接口(Cloneable),可比較接口(Comparable)。

ActionListener

運行效果如圖所示:

實現的源代碼如下所示:

package Blog;

import javax.swing.*;

public class blogTryProject {
	public static void main(String[] args) {
		HandleEvent he = new HandleEvent();
		he.main(args);
	}
}
//ActionListener監聽器接口
class HandleEvent extends JFrame{
	public HandleEvent(){
		JButton jbtOk = new JButton("Ok");
		JButton jbtCancel = new JButton("Cancel");
		JPanel p = new JPanel();
		p.add(jbtOk);
		p.add(jbtCancel);
		add(p);
		
		OkListenerClass listener1 = new OkListenerClass();
		CancelListenerClass listener2 = new CancelListenerClass();
		//條件二:使用source.addActionListener(listener)註冊源對象
		jbtOk.addActionListener(listener1);
		jbtCancel.addActionListener(listener2);
	}
	public static void main(String[]args){
		JFrame frame = new HandleEvent();
		frame.setTitle("Handle Event");
		frame.setSize(200, 150);
		frame.setLocation(200, 100);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}
//條件一:使得OkListenerClass成爲監聽器類的實例,並實現其方法
class OkListenerClass implements java.awt.event.ActionListener{
	//事件actionPerformed方法的實現
	public void actionPerformed(java.awt.event.ActionEvent e){
		System.out.println("Ok button clicked");
	}
}
class CancelListenerClass implements java.awt.event.ActionListener{
	public void actionPerformed(java.awt.event.ActionEvent e){
		System.out.println("Cancel button clicked");
	}
}
Cloneable(注意克隆不成功會有異常拋出,可參考《Java基本功練習十八》)

運行效果如圖所示:

實現的源代碼如下所示:

package Blog;

public class blogTryProject {
	public static void main(String[] args) throws CloneNotSupportedException {
		House house = new House(12,89);
		house.main(args);
	}
}
//Cloneable接口範例
class House implements Cloneable,Comparable{
	private int id;
	private double area;
	private java.util.Date whenBuilt;
	public House(int id,double area){
		this.id = id;
		this.area = area;
		whenBuilt = new java.util.Date();
	}
	
	public int getId(){
		return id;
	}
	public double getArea(){
		return area;
	}
	public java.util.Date getWhenBuilt(){
		return whenBuilt;
	}
	//覆蓋Object中保護類型的clone()方法,並增強其可見性爲public
	public Object clone() throws CloneNotSupportedException{
		return super.clone();
	}
	public int compareTo(Object o){
		if(area > ((House)o).area)
			return 1;
		else if(area < ((House)o).area)
			return -1;
		else
			return 0;
	}
	public String toString(){
		return "House的信息,ID爲:"+id+"\t面積爲:"+area;
	}
	public boolean equals(Object o){
		if(id == ((House)o).id && area == ((House)o).area)
			return true;
		else
			return false;
	}
	public static void main(String[]args) throws CloneNotSupportedException{
		House house1 = new House(502, 123);
		House house2 = new House(503, 223);
		House house3 = (House)house1.clone();
		System.out.println("house1的信息爲:"+house1.toString());
		System.out.println("house2的信息爲:"+house2.toString());
		System.out.println("house3的信息爲:"+house3.toString());
		System.out.println("house1 與 house2 的面積大小比較:"+house1.compareTo(house2));
		System.out.println("house1 與 house3 是否內容相同? "+house1.equals(house3));
		System.out.println("house1 與 house3 是否引用變量相同? "+(house1 == house3));
	}
}
Comparable

運行效果如圖所示:

實現的源代碼如下所示:

package Blog;

public class blogTryProject {
	public static void main(String[] args){
		TestComparableRectangle tcr = new TestComparableRectangle();
		tcr.main(args);
	}
}
//Comparable接口實現範例
/*
Comparable的接口定義如下
package java.lang;
public interface Comparable{
  public int compareTo(Object o);
}
*/
class ComparableRectangle extends Rectangle implements Comparable{
	//構造函數
	public ComparableRectangle(double width,double height){
		super(width,height);
	}
	//Comparable接口的實現
	public int compareTo(Object o){
		if(getArea() > ((ComparableRectangle)o).getArea())
			return 1;
		else if(getArea() < ((ComparableRectangle)o).getArea())
			return -1;
		else
			return 0;
	}
	//利用接口新定義一個比較兩個矩形面積的靜態方法
	public static Comparable max(Comparable o1,Comparable o2){
		if(o1.compareTo(o2) > 0)
			return o1;
		else
			return o2;
	}
}
//測試Comparable接口程序
class TestComparableRectangle{
	public static void main(String[]args){
		ComparableRectangle tcr1 = new ComparableRectangle(2, 5);
		ComparableRectangle tcr2 = new ComparableRectangle(3, 6);
		System.out.println("\nComparable接口演示範例");
		System.out.println("兩個矩形的信息如下");
		System.out.println(tcr1.toString());
		System.out.println(tcr2.toString());
		System.out.println("tcr1 和 tcr2 比較結果爲:"+tcr1.compareTo(tcr2));
		System.out.println("面積大者的信息如下\n"+tcr1.max(tcr1, tcr2));
	}
}


//矩形類
class Rectangle extends GeometricObject{
	private double width;
	private double height;
	public Rectangle(){
	}
	public Rectangle(double width,double height){
		this.width = width;
		this.height = height;
	}
	public Rectangle(double width,double height,String color,boolean filled){
		this.width = width;
		this.height = height;
		setColor(color);
		setFilled(filled);
	}
	public double getWidth(){
		return width;
	}
	public void setWidth(double width){
		this.width = width;
	}
	
	public double getHeight(){
		return height;
	}
	public void setHeight(double height){
		this.height = height;
	}
	
	public double getArea(){
		return width * height;
	}
	
	public double getPerimeter(){
		return 2 * (width + height);
	}
	public String toString(){
		return super.toString()+"\n寬爲:"+getWidth()+"\t\t長爲:"+getHeight();
	}
}

//抽象類GeometricObject
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 void setFilled(boolean filled){
		this.filled = filled;
	}
	public java.util.Date getDateCreated(){
		return dateCreated;
	}
	public String toString(){
		return "created on "+dateCreated+"\ncolor: "+color+"\t\tfilled: "+filled;
	}
	public abstract double getArea();
	public abstract double getPerimeter();
}

範例四:包裝類範例。Java提供一個方便的辦法,將基本數據類型併入對象或包裝成對象,稱爲包裝類

運行效果如圖所示:

實現的源代碼如下所示:

package Blog;

public class blogTryProject {
	public static void main(String[] args){
		GenericSort gc = new GenericSort();
		gc.main(args);
	}
}
//對象數組排序範例
class GenericSort{
	public static void main(String[]args){
		System.out.println("對象數組排序範例");
		Integer[] intArray = {new Integer(2),new Integer(4),new Integer(3)};
		Double[] doubleArray = {new Double(3.4),new Double(1.3),new Double(-22.1)};
		Character[] charArray = {new Character('a'),new Character('J'),new Character('r')};
		String[] stringArray = {"Tom","John","Fred"};
		sort(intArray);
		sort(doubleArray);
		sort(charArray);
		sort(stringArray);
		System.out.println("Sorted Integer objects:");
		printList(intArray);
		System.out.println("Sorted Double objects:");
		printList(doubleArray);
		System.out.println("Sorted Character objects:");
		printList(charArray);
		System.out.println("Sorted String objects:");
		printList(stringArray);
	}
	public static void sort(Comparable[] list){
		Comparable currentMin;
		int currentMinIndex;
		for(int i = 0;i < list.length - 1;i++){
			currentMin = list[i];
			currentMinIndex = i;
			for(int j = i + 1;j < list.length;j++){
				if(currentMin.compareTo(list[j]) > 0){
					currentMin = list[j];
					currentMinIndex = j;
				}
			}
			if(currentMinIndex != i){
				list[currentMinIndex] = list[i];
				list[i] = currentMin;
			}
		}
	}
	public static void printList(Object[] list){
		for(int i = 0;i < list.length;i++)
			System.out.print(list[i]+" ");
		System.out.println();
	}
}

範例五:有理數類的加減乘除實現。

運行效果如圖所示:

實現的源代碼如下所示:

package Blog;

public class blogTryProject {
	public static void main(String[] args){
		TestRational tr = new TestRational();
		tr.main(args);
	}
}
//有理數類測試
class TestRational{
	public static void main(String[]args){
		Rational r1 = new Rational(4,2);
		Rational r2 = new Rational(2,3);
		
		System.out.println(r1+" + "+r2+" = "+r1.add(r2));
		System.out.println(r1+" - "+r2+" = "+r1.subtract(r2));
		System.out.println(r1+" * "+r2+" = "+r1.multiply(r2));
		System.out.println(r1+" / "+r2+" = "+r1.divide(r2));
		System.out.println(r2+" is "+r2.doubleValue());
	}
}
//有理數類實現
class Rational extends Number implements Comparable{
	private long numerator = 0;
	private long denominator = 1;
	public Rational(){
		this(0,1);
	}
	public Rational(long numerator,long denominator){
		long gcd = gcd(numerator,denominator);
		this.numerator = ((denominator > 0) ? 1 : -1) * numerator / gcd;
		this.denominator = Math.abs(denominator) / gcd;
	}
	private static long gcd(long n,long d){
		long n1 = Math.abs(n);
		long n2 = Math.abs(d);
		int gcd = 1;
		for(int k = 1;k <= n1 && k <= n2;k++){
			if(n1 % k == 0 && n2 % k == 0)
				gcd = k;
		}
		return gcd;
	}
	public long getNumerator(){
		return numerator;
	}
	public long getDenominator(){
		return denominator;
	}
	public Rational add(Rational secondRational){
		long n = numerator * secondRational.getDenominator() +
				denominator * secondRational.getNumerator();
		long d = denominator * secondRational.getDenominator();
		return new Rational(n,d);
	}
	public Rational subtract(Rational secondRational){
		long n = numerator * secondRational.getDenominator() -
				denominator * secondRational.getNumerator();
		long d = denominator * secondRational.getDenominator();
		return new Rational(n,d);
	}
	public Rational multiply(Rational secondRational){
		long n = numerator * secondRational.getNumerator();
		long d = denominator * secondRational.getDenominator();
		return new Rational(n,d);
	}
	public Rational divide(Rational secondRational){
		long n = numerator * secondRational.getDenominator();
		long d = denominator * secondRational.numerator;
		return new Rational(n,d);
	}
	public String toString(){
		if(denominator == 1)
			return numerator +"";
		else
			return numerator+"/"+denominator;
	}
	public boolean equals(Object parm1){
		if((this.subtract((Rational)(parm1))).getNumerator() == 0)
			return true;
		else
			return false;
	}
	public int intValue(){
		return (int)doubleValue();
	}
	public float floatValue(){
		return (float)doubleValue();
	}
	public double doubleValue(){
		return numerator * 1.0 / denominator;
	}
	public long longValue(){
		return (long)doubleValue();
	}
	public int compareTo(Object o){
		if((this.subtract((Rational)o)).getNumerator() > 0)
			return 1;
		else if((this.subtract((Rational)o)).getNumerator() < 0)
			return -1;
		else
			return 0;
	}
	
}

範例六:接口和抽象類簡單實例的實現對比。

運行效果如圖所示:

實現的源代碼如下所示:

package Blog;

public class blogTryProject {
	public static void main(String[] args){
		ChouXiangAnimal cxa = new ChouXiangAnimal();
		cxa.main(args);
		JieKouAnimal jka = new JieKouAnimal();
		jka.main(args);
	}
}
//接口和抽象類的優劣比較
//抽象類實現的方式
class ChouXiangAnimal{
	public static void main(String[]args){
		//抽象類實現Animal
		System.out.println("抽象類實現Animal");
		NewAnimal animal = new NewChicken();
		eat(animal);
		animal = new Duck();
		eat(animal);
	}
	public static void eat(NewAnimal animal){
		System.out.println(animal.howToEat());
	}
}
abstract class NewAnimal{
	public abstract String howToEat();
}
class NewChicken extends NewAnimal{
	public String howToEat(){
		return "NewChicken: Fry it";
	}
}
class Duck extends NewAnimal{
	public String howToEat(){
		return "Duck: Roast it";
	}
}
//接口實現方式
class JieKouAnimal{
	public static void main(String[]args){
		//接口實現的Animal
		System.out.println("接口實現的Animal");
		NewEdible stuff = new NewChicken1();
		eat(stuff);
		stuff = new Duck1();
		eat(stuff);
		stuff = new Broccoli();
		eat(stuff);
	}
	public static void eat(NewEdible stuff){
		System.out.println(stuff.howToEat());
	}
}
interface NewEdible{
	public String howToEat();
}
class NewChicken1 implements NewEdible{
	public String howToEat(){
		return "NewChicken1: Fry it";
	}
}
class Duck1 implements NewEdible{
	public String howToEat(){
		return "Duck1: Fry it";
	}
}
class Broccoli implements NewEdible{
	public String howToEat(){
		return "Broccoli: Stir-fry it";
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章