抽象类和接口
一、抽象类
在类层次结构中,类的位置越高,其定义的抽象程度也就越高。在定义类层次结构中的过程中,有一些类确定了子类的通用的行为和属性,而且这些类不能被实例化用限定符abstract来声明。这些类称为抽象类。
l 抽象类可以包含常规类能够包含的任何东西,包括构造方法,因为子类可能需要继承这种方法。
l 抽象类也可以包含抽象方法,也就是没有实现的方法,而这些方法在子类中被实现。不能在非抽象类中声明抽象方法。
l 如果一个抽象类中除了抽象方法外什么都没有,则最好使用接口。
二、接口
与抽象类和抽象方法一样,接口也是提供了其他类要实现的行为模板。
使用和实现接口l 要使用接口,可以在类定义中包含关键字implements
l 包含接口后,必须实现该接口中的所有方法,而不能有选择地实现其中的某些。
l 类实现接口后,子类将继承该接口中的所有方法,并可以覆盖或重载它们。
l 若类继承了一个实现了某一接口的超类,则不必在本类中又implements一次。
l 要在类中使用多个接口,只需要将它们的名称用逗号分开。
使用多个接口时如果两个接口定义了相同的方法,则应注意以下规则:l 如果两个方法的特征标相同,可以在类中实现一个方法,其定义能够满足两个接口。
l 如果方法的参数列表不同,则是一种简单的方法重载:实现两种方法特征标,分别满足两个接口的需要。
l 如果方法的参数列表相同,但返回值不同,则无法创建一个能够满足两个接口的方法。这时,编译会出错。
创建接口的规定:
l 创建接口要用interface,而不是class。
l 如果接口前没有限定符,则自动被转换为abstract和public的,而且不能在接口内将方法声明为私有的或是保护的。
l 除了方法外,接口还可以包含变量,但它们必须是公有、静态和final的(常量)。或者不使用限定符,这样会自动声明为这些限定,而且变量须赋值。
l 如果声明接口时没有使用pulbic,则接口不会自动将方法转换为公有和抽象的,也不会将常量转换为公有的。而非公有接口的方法和常量也是非公有的,这些方法和常量只能被同一个包中的类和其他接口使用。
l 与类一样,接口也可以属于某个包。接口还可以导入其他包中的接口和类,就像类一样。
l 接口可以继承另一个接口,此时‘子接口’将获得‘超接口’中声明的所有方法定义和常量。这时要使用extends扩展。
l 另外,不同于类,接口可以多重继承,新接口将包含其父接口中的方法和常量。(多继承约束参见本话题之上的一个话题)
三、实例
创建一个网上商店,应用程序Storefront使用了包、访问控制、接口和封装。主要处理两项任务:
l 根据库存量计算每种商品的销售价格;
l 按照销售价格对商品排序;
Item类
package com.prefect.ecommerce;
/**
* 本类实现了Comparable接口,这个接口使得对类的对象进行排序更容易。
* 这个接口只有一个方法compareTo(Object),返回一个整数,功能是比较
* 两个对象:
* 若当前对象应排列在另一个之前,返回-1
* 若当前对象应排列在另一个之后,返回1
* 两个对象相等,则返回0
* */
public class Item implements Comparable
{
private String id;
private String name;
private double retail;
private int quantity;
private double price;
Item(String id,String name,String retail,String quan)
{
this.id = id;
this.name = name;
this.retail = Double.parseDouble(retail);
this.quantity = Integer.parseInt(quan);
if(this.quantity > 400)
{
this.price = this.retail * .5D;
}
else if(this.quantity > 200)
this.price = this.retail * .6D;
else
this.price = this.retail * .7D;
//对price四舍五入,Math.floor()表示将小数舍入为与之最接近且不大于它的整数
//并返回double
price = Math.floor(price * 100 + .5)/100;
}
//compareTo()方法需要决定根据哪个实例变量来对对象进行排序,这里根据price
public int compareTo(Object o)
Item temp = (Item)o;
if(this.price < temp.price)
return 1;
else if(this.price > temp.price)
return -1;
return 0;
public String getId()
return id;
public String getName()
return name;
public double getPrice()
return price;
public int getQuantity()
return quantity;
public double getRetail()
return retail;
}
Storefont类
*用于管理商店中的商品,每一种商品都是一个Item对象,他们被存储在链表中
*/
import java.util.Collections;
import java.util.LinkedList;
public class Storefont
//创建一个链表
private LinkedList catalog = new LinkedList();
//将item加入到链表中
public void addItem(String id, String name, String price, String quant)
Item it = new Item(id, name, price, quant);
//在链表中添加对象的方法
catalog.add(it);
//返回当前的item,使用索引i来读取他们
public Item getItem(int i)
//读取链表中的索引
return (Item) catalog.get(i);
//返回链表中的对象数
public int getSize()
//链表的大小
return catalog.size();
public void sort()
//此方法对链表和其他数据结果中的对象进行排序,期间将调用对象的
//comparaTo()方法来确定排序
Collections.sort(catalog);
}
GiftShop类
public class GiftShop
public static void main(String[] args)
Storefont store = new Storefont();
//添加商品
store.addItem("C01","MUG","9.99","150");
store.addItem("C02","LG MUG","12.99","82");
store.addItem("C03","MOUSEPAD","10.49","800");
store.addItem("D01","T SHIRT","16.99","90");
//进行排序
store.sort();
//输出排序后的结果
for(int i = 0 ; i < store.getSize() ; i++)
Item show = (Item)store.getItem(i);
System.out.println("\nItem ID:" + show.getId()
+ "\nName:" + show.getName()
+ "\nRetail Price:$" + show.getRetail()
+ "\nPrice:$" + show.getPrice()
+ "\nQuantity:" + show.getQuantity());
运行结果
Item ID:D01
Name:T SHIRT
Retail Price:$16.99
Price:$11.89
Quantity:90
Item ID:C02
Name:LG MUG
Retail Price:$12.99
Price:$9.09
Quantity:82
Item ID:C01
Name:MUG
Retail Price:$9.99
Price:$6.99
Quantity:150
Item ID:C03
Name:MOUSEPAD
Retail Price:$10.49
Price:$5.25
Quantity:800