您的位置:首页 > 编程语言 > Java开发

Java基本功练习十六(继承和多态【继承多态覆盖练习、多重继承、数组线性表ArrayList、银行账户类升级】)

2014-12-28 09:28 801 查看
本博文将讲述类的继承和多态的相关情况。

在面向对象程序设计中,可以从已有的类派生出新类,这称为继承。继承是Java在软件重用方面一个重要且功能强大的特征。假设要定义一个类,对圆、矩形和三角形建模。这些类有很多特性。设计这些类来避免冗余并使系统更易于理解和维护的最好办法就是继承。
面向对象语言中,接口的多种不同的实现方式即为多态。多态性是允许将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。归结为一句话:允许将子类类型赋值给父类类型,这有别与C++中的多态(通过虚函数实现)。

范例一:继承多态基本概念用法练习。

运行效果如图:



其实现的源代码如下所示:(其中包括自定义一个堆栈类MyStack的实现)
package Blog;

import java.util.Date;

public class blogTryProject{
public static void main(String[] args) {
//父类与子类
TestCircleRectangle tcr = new TestCircleRectangle();
tcr.main(args);

//动态绑定
System.out.println("\n动态绑定实例演示");
m(new GraduateStudent());
m(new Student());
m(new Person());
m(new Object());

//继承与多态
System.out.println("\n多态和类型转换演示");
CastingDemo cd = new CastingDemo();
cd.main(args);

//ArrayList数组线性表
System.out.println("\nArrayList数组线性表");
TestArrayList tal = new TestArrayList();
tal.main(args);

}
public static void m(Object x){
System.out.println(x.toString());
}
}
//MyStack自定义栈类
class MyStack{
private java.util.ArrayList list = new java.util.ArrayList();

public boolean isEmpty(){
return list.isEmpty();
}
public int getSize(){
return list.size();
}
public Object peek(){
return list.get(getSize() - 1);
}
public Object pop(){
Object o = list.get(getSize() - 1);
list.remove(getSize() - 1);
return o;
}
public void push(Object o){
list.add(o);
}
public int search(Object o){
return list.lastIndexOf(o);
}
public String toString(){
return "Stack: "+list.toString();
}
}

//ArrayList数组线性表
class TestArrayList{
public static void main(String[]args){
java.util.ArrayList cityList = new java.util.ArrayList();
cityList.add("London");
cityList.add("Denver");
cityList.add("Paris");
cityList.add("Miami");
cityList.add("Seoul");
cityList.add("Tokyo");

System.out.println("List size? "+cityList.size());
System.out.println("Is Miami in the list ? "+cityList.contains("Miami"));
System.out.println("The location fo Denver in the list ?"+cityList.indexOf("Denver"));
System.out.println("Is the list empty? "+cityList.isEmpty());

cityList.add(2, "Xian");
cityList.remove("Miami");
cityList.remove(1);
System.out.println(cityList.toString());

for(int i = cityList.size() - 1;i >= 0;i--)
System.out.print(cityList.get(i)+" ");
System.out.println();

java.util.ArrayList list = new java.util.ArrayList();
list.add(new Circle1(2));
list.add(new Circle1(3));
System.out.println("The area of the circle? "+((Circle1)list.get(0)).getArea());

}
}

//多态和类型转换
class CastingDemo{
public static void main(String[]args){
Object object1 = new Circle1(1);
Object object2 = new Rectangle1(1,1);
displayObject(object1);
displayObject(object2);
}
public static void displayObject(Object object){
if(object instanceof Circle1){
System.out.println("The circle diameter is "+((Circle1)object).getDiameter());
System.out.println("The circle area is "+((Circle1)object).getArea());
}
else if(object instanceof Rectangle1){
System.out.println("The rectangle area is "+((Rectangle1)object).getArea());
}
}
}

//动态绑定实例
class DynamicBindingDemo{
public static void main(String[]args){

}
}
class GraduateStudent extends Student{
}
class Student extends Person{
public String toString(){
return "Student";
}
}
class Person extends Object{
public String toString(){
return "Person";
}
}

//父类子类继承及其使用
class TestCircleRectangle{
public static void main(String[]args){
System.out.println("父类子类继承及其使用");
Circle1 circle = new Circle1(5);
System.out.println("A circle "+circle.toString());
System.out.println("The radius is "+circle.getRadius());
System.out.println("The area is "+circle.getArea());
System.out.println("The diameter is "+circle.getDiameter());

Rectangle1 rectangle = new Rectangle1(2,4,"Yellow",true);
System.out.println("\nA rectangle "+rectangle.toString());
System.out.println("The area is "+rectangle.getArea());
System.out.println("The perimeter is "+rectangle.getPerimeter());
}
}

class GeometricObject1{
private String color = "White";
private boolean filled;
private java.util.Date dateCreated;

public GeometricObject1(){
dateCreated = new java.util.Date();
}

public GeometricObject1(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;
}
}

class Circle1 extends GeometricObject1{
private double radius;
public Circle1(){
}
public Circle1(double radius){
this.radius = radius;
}

public Circle1(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 getDiameter(){
return 2 * radius;
}

public void printCircle(){
System.out.println("The circle is created "+getDateCreated()+
" and the radius is "+radius);
}
}

class Rectangle1 extends GeometricObject1{
private double width;
private double height;
public Rectangle1(){
}

public Rectangle1(double width,double height){
this.width = width;
this.height = height;
}
public Rectangle1(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);
}

}

范例二:多重继承的实现。Person类,有Student类和Employee类继承Person,而Employee类又被教员类Faculty类和职员类Staff类继承。每个人都有姓名、地址、电话号码和电子邮件地址。学生有年级状态(大一到大四)。一个雇员有办公室、工资和受聘日期。教员有办公时间和级别。职员有职务称号。覆盖每个类的toString()方法,显示相应的类名和人名。编写一个测试程序,创建Person、Student、Employee、Faculty和Staff,并且调用它们的toString()方法。
运行效果如图所示:



其实现的源代码如下所示:

package Blog;

import java.util.Date;

public class blogTryProject{
public static void main(String[] args) {
TestPerson person = new TestPerson();
person.main(args);
}
}
//多重继承的练习
class TestPerson{
public static void main(String[]args){
Person1 person = new Person1();
System.out.println(person.toString());

Student1 st = new Student1();
System.out.println(st.toString());

Employee employee = new Employee();
System.out.println(employee.toString());

Faculty faculty = new Faculty();
System.out.println(faculty.toString());
}
}
class Person1{
private String name;
private String address;
private String phone;
private String addressOfMessage;
public Person1(){
this("公安局警官","上海市长宁路","110","110@126.com");
}
public Person1(String name,String address,String phone,String addressOfMessage){
this.name = name;
this.address = address;
this.phone = phone;
this.addressOfMessage = addressOfMessage;
}
public String getName(){
return this.name;
}
public String getAddress(){
return this.address;
}
public String getPhone(){
return this.phone;
}
public String getAddressOfMessage(){
return this.addressOfMessage;
}
public String toString(){
return "\n此人的基本信息如下\n姓名:"+this.getName()+"\n地址: "+this.getAddress()+
"\n电话:"+this.getPhone()+"\n邮箱:"+this.getAddressOfMessage()+"\n";
}
}
class Student1 extends Person1{
private String status;

public Student1(){
this("大一","链条哥","上海市浦东新区海科路","13977998876","liantiaoge@126.com");
}
public Student1(String status,String name,String address,
String phone,String addressOfMessage){
super(name,address,phone,addressOfMessage);
this.status = status;
}
public String getStatus(){
return this.status;
}
public String toString(){
return super.toString()+"学生\n年纪为:"+this.getStatus()+"\n";
}
}
class Employee extends Person1{
private String office;
private String salary;
private java.util.Date dateOfEmployeed;

public Employee(){
this("浩哥","上海市浦东新区99号","13944533343","123@126.com",
"小卫星502室","工资8000rmb",new java.util.Date());
}
public Employee(String name,String address,String phone,String addressOfMessage,
String office,String salary,java.util.Date dateOfEmployeed){
super(name,address,phone,addressOfMessage);
this.office = office;
this.salary = salary;
this.dateOfEmployeed = dateOfEmployeed;
}
public String getOffice(){
return this.office;
}
public String getSalary(){
return this.salary;
}
public java.util.Date getDateOfEmployeed(){
return this.dateOfEmployeed;
}
public String toString(){
return super.toString()+"办公室:"+this.getOffice()+
"\n薪水:"+this.getSalary()+"\n受聘日期:"+this.getDateOfEmployeed();
}
}
class Faculty extends Employee{
private String time;
private String status;

public Faculty(){
this("老三","上海市浦东新区100号","13387654563","123567@126.com",
"小卫星502室","工资8000rmb",new java.util.Date(),
"周一到周五上午9点到下午5点","导航室工程师");
}
public Faculty(String name,String address,String phone,String addressOfMessage,
String office,String salary,java.util.Date dateOfEmployeed,
String time,String status){
super(name,address,phone,addressOfMessage,office,salary,dateOfEmployeed);
this.time = time;
this.status = status;
}
public String getTime(){
return this.time;
}
public String getStatus(){
return this.status;
}
public String toString(){
return super.toString()+"\n职员\n工作时间:"+this.getTime()+
"\n级别:"+this.getStatus();
}
}


范例三:数组线性表ArrayList的是要用及实现。
其UML类图如下所示:




运行效果如图所示:第一张为使用效果图;第二张为实现效果图。





其实现的源代码如下所示:
ArrayList的使用
package Blog;

import java.util.Date;
import java.util.ArrayList;

public class blogTryProject{
public static void main(String[] args) {
MyArrayList mal = new MyArrayList();
mal.main(args);
}
}
//数组线性表ArrayList范例
class MyArrayList{
public static void main(String[]args){
System.out.println("数组线性表ArrayList使用范例");
ArrayList list = new ArrayList();
MyArrayList tal1 = new MyArrayList();
MyArrayList tal2 = new MyArrayList();
MyArrayList tal3 = new MyArrayList();
MyArrayList tal4 = new MyArrayList();
MyArrayList tal5 = new MyArrayList();

list.add(tal1);
list.add(tal2);
list.add(tal3);
list.add("I Love Java");

System.out.println("\n线性表的长度为:"+list.size());
System.out.println("线性表所包含的元素为:");
for(int i = 0;i < list.size();i++){
System.out.println(list.get(i));
}

list.remove(0);
System.out.println("\n删除第一个元素后新的list为:");
for(int i = 0;i < list.size();i++){
System.out.println(list.get(i));
}

list.add(0,tal4);
System.out.println("\n在第一个位置添加新元素后新的list为:");
for(int i = 0;i < list.size();i++){
System.out.println(list.get(i));
}

list.set(0, tal4);
System.out.println("\n在第一个位置设置新元素后新的list为:");
for(int i = 0;i < list.size();i++){
System.out.println(list.get(i));
}

System.out.println("\nlist中是否包含d? "+list.contains(tal2));
System.out.println("\nlist中是否包含d? "+list.contains(tal5));
}
}


ArrayList的实现
package Blog;

import java.util.Date;
import java.util.ArrayList;

public class blogTryProject{
public static void main(String[] args) {
TestArrayListOfDesign tal = new TestArrayListOfDesign();
tal.main(args);
}
}
class TestArrayListOfDesign{
public static void main(String[]args){
System.out.println("ArrayList的实现范例");
NewCourse course = new NewCourse("English");
java.util.Date date = new java.util.Date();
String s = "I Love Java";
javax.swing.JFrame frame = new javax.swing.JFrame();
Person person = new Person();
ArrayListOfDesign list = new ArrayListOfDesign();

list.add(course);
list.add(date);
list.add(s);
list.add(frame);
list.add(person);
System.out.println("元素对象个数为:"+list.size());
for(int i = 0;i < list.size();i++)
System.out.println(list.get(i).toString());

list.remove(0);
System.out.println("移除掉第一个元素后,list中的元素为:");
for(int i = 0;i < list.size();i++)
System.out.println(list.get(i).toString());

System.out.println("\"I Love Java\"在第"+list.indexOf("I Love Java")+"个位置上");

list.set(list.indexOf("I Love Java"), "I Love Java and C++");
System.out.println("将I Love Java 设置为 I Love Java and C++后list中的元素为:");
for(int i = 0;i < list.size();i++)
System.out.println(list.get(i).toString());

list.clear();
System.out.print("清除之后,元素个数为:");
for(int i = 0;i < list.size();i++)
System.out.println(list.get(i).toString());
System.out.println(list.size());
}
}

//ArrayList的实现
class ArrayListOfDesign{
private int numberOfCount;
private Object[] list;
ArrayListOfDesign(){
this.list = new Object[10];
}
public void add(Object o){
if(numberOfCount > numberOfCount){
Object[] newList = new Object[numberOfCount * 2];
System.arraycopy(list, 0, newList, 0, numberOfCount);
list = newList;
}
list[numberOfCount++] = o;
}
public void add(int index,Object o){
Object temp = new Object();
numberOfCount++;
for(int i = numberOfCount - 1;i >= index + 1;i--){
list[i] = list[i - 1];
}
list[index] = temp;
}
public void clear(){
Object obj = new Object();
for(int i = numberOfCount - 1;i >= 0;i--){
list[i] = obj;
numberOfCount--;
}
}
public boolean contains(Object o){
boolean flag = false;
for(int i = 0;i < numberOfCount;i++){
if(list[i] == o){
flag = true;
break;
}
}
return flag;
}
public Object get(int index){
return list[index];
}
public int indexOf(Object o){
int index = -1;
for(int i = 0;i < numberOfCount;i++){
if(list[i] == o){
index = i;
break;
}
}
return index;
}
public boolean isEmpty(){
if(numberOfCount != 0)
return true;
else
return false;
}
public int lastIndexOf(Object o){
int index = -1;
for(int i = numberOfCount - 1;i >= 0;i--){
if(list[i] == o){
index = i;
break;
}
}
return index;
}
public void remove(Object o){
Object obj = new Object();
for(int i = 0;i < numberOfCount;i++){
if(list[i] == o){
if(i == numberOfCount - 1){
list[i] = obj;
numberOfCount--;
}
else{
for(int j = i;j < numberOfCount - 1;j++){
list[j] = list[j+1];
}
list[numberOfCount - 1] = obj;
numberOfCount--;
}
}
}
}
public int size(){
return numberOfCount;
}
public void remove(int index){
Object obj = new Object();
for(int i = index;i < numberOfCount;i++)
list[i] = list[i+1];
list[numberOfCount - 1] = obj;
numberOfCount--;
}
public void set(int index,Object o){
list[index] = o;
}
}
//选课系统类的实现
class NewCourse{
private String courseName;
private ArrayList studentList = new ArrayList();

public NewCourse(String courseName){
this.courseName = courseName;
}

public void addStudent(String student){
this.studentList.add(student);
}

public ArrayList getStudents(){
return this.studentList;
}

public int getNumberOfStudents(){
return this.studentList.size();
}

public String getCourseName(){
return this.courseName;
}

public void dropStudent(String student){
int index = this.studentList.indexOf(student);
this.studentList.remove(index);
}

public void clear(String courseName){
this.studentList.clear();
}
}
//Person类的实现
class Person{
private String name;
private String address;
private String phone;
private String addressOfMessage;
public Person(){
this("公安局警官","上海市长宁路","110","110@126.com");
}
public Person(String name,String address,String phone,String addressOfMessage){
this.name = name;
this.address = address;
this.phone = phone;
this.addressOfMessage = addressOfMessage;
}
public String getName(){
return this.name;
}
public String getAddress(){
return this.address;
}
public String getPhone(){
return this.phone;
}
public String getAddressOfMessage(){
return this.addressOfMessage;
}
public String toString(){
return "\n此人的基本信息如下\n姓名:"+this.getName()+"\n地址: "+this.getAddress()+
"\n电话:"+this.getPhone()+"\n邮箱:"+this.getAddressOfMessage()+"\n";
}
}

范例四:升级银行账户类Acount(《Java基本功练习十五》中的ATM机模拟中的账户类Acount)。
升级的要求如下:
1)添加一个String类型的name存储客户的名字;

2)添加一个新的构造方法,该方法创建一个带指定名字、id和收支额的账户;
3)添加一个名为transaction的新数据域,它的类型为ArrayList,可以为账户存储交易。每笔交易就是一个
Transaction类的实例。Transaction类的定义如下图所示。
4)修改withdraw和deposit方法,向transactions数组线性表添加一笔交易。
编写一个测试程序,创建一个年利率为1.5%,收支额为1000,id为1122,而名字为George的Acount。向该账户存入30,40,50,并从账户取出5,4,3圆。打印账户清单,显示账户持有者名字、收支额和所有的交易。
Transaction的UML类图:


运行效果如图所示:



实现的源代码如下所示:
package Blog;

import java.util.Date;
import java.util.ArrayList;

public class blogTryProject{
public static void main(String[] args) {
TestAcount ta = new TestAcount();
ta.main(args);
}
}
//TestAcount的测试程序
class TestAcount{
public static void main(String[]args){
Acount a = new Acount();
long time = System.currentTimeMillis();
a.deposit('D', 30,time);//模拟存取款时的时间
a.deposit('D', 40,time + 100000000);
a.deposit('D', 50,time + 200000000);
a.withDraw('W', 5,time + 400000000);
a.withDraw('W', 4,time + 800000000);
a.withDraw('W', 3,time + 1600000000);
a.printJiLu();
System.out.println("账户创建日期为:"+a.getDateCreated());
}
}
//Acount类的升级
class Acount{
private String name;
private int id;
protected double balance;
private double annualInterestRate;
private Date dateCreated;
private ArrayList jiaoyijilu = new ArrayList();

Acount(){
this("George",1122,1000,1.5);
}
Acount(String name,int id,double balance,double annualInterestRate){
this.name = name;
this.id = id;
this.balance = balance;
this.annualInterestRate = annualInterestRate;
dateCreated = new Date();
}
public int getId(){
return id;
}
public void setId(int newID){
id = newID;
}
public double getBalance(){
return balance;
}
public void setBalance(double newBalance){
balance = newBalance;
}
public double getAnnualInterestRate(){
return annualInterestRate;
}
public void setAnnualInterestRate(double newRate){
annualInterestRate = newRate;
}
public String getDateCreated(){
return dateCreated.toString();
}
public double getMonthlyInterestRate(){
return annualInterestRate / 12.0;
}
public void withDraw(char type,double amount,long elapstime){
Date date = new Date(elapstime);
Transaction actions = new Transaction(type,amount,balance,date);
jiaoyijilu.add(actions);
balance = actions.getNewBalance();
}
public void deposit(char type,double amount,long elapstime){
Date date = new Date(elapstime);
Transaction actions = new Transaction(type,amount,balance,date);
jiaoyijilu.add(actions);
balance = actions.getNewBalance();
}
public void printJiLu(){
System.out.println("名为:"+name+" ID: "+id+" 的账户交易记录如下:");
for(int i = 0;i < jiaoyijilu.size();i++){
System.out.println(jiaoyijilu.get(i).toString());
}
}
}
//交易记录类
class Transaction extends Acount{
private char type;
private double amount;
private double newBalance;
private String description;

public Transaction(char type,double amount,double balance,Date date){
if(type == 'W'){
newBalance = balance;
newBalance -= amount;
description = date.toString()+" 取款 "+amount+" 可用余额为:"+newBalance;
}
else if(type == 'D'){
newBalance = balance;
newBalance += amount;
description = date.toString()+" 存款 "+amount+" 可用余额为:"+newBalance;
}
}
public double getNewBalance(){
return newBalance;
}
public String toString(){
return description;
}
}


总结:
a.继承的注意点
1)和传统理解上相反,子类并不是父类的一个子集。实际上一个子类通常比它的父类包含更多的信息
和方法;

2)父类中的私有数据域在该类之外是不可访问的。因此,不能在子类中直接使用它们。但是,如果父类中
定义 了公共的访问/修改器,那么可以通过set和get方法修改和访问它们;
3)不是所有的是关系(is-a)都该用继承来建模的。如果要用B类去扩展类A,那么A应该要比B包含更多的信息;

4)继承是用来为是(is-a)关系建模的。不要仅仅为了重用方法这个原因而盲目的扩展一个类。一个父类和它的子
类之间必须存在是关系;

5)某些程序设计语言允许从几个类派生出一个子类的。这种能力称为多重继承。但在Java中,不允许多重
继承。一个Java类只可能直接继承一个父类。这中限制称为单一继承。如果使用extends关键字来定义一个子
类,它只允许有一个父类。然后,多重继承是可以通过接口来实现的,
b.super关键字

子类继承它的父类所有可访问的数据域和方法,同样可以用super关键字继承其构造方法和方法。
c.覆盖和重载的区别

重载方法意味着可以定义多个同名的方法,但这些方法具有不同的签名。覆盖方法意味着为子类中的方法提供一个全新的实现。该方法已经在父类中定义。

为了覆盖方法,这个方法必须使用相同的签名以及相同的返回值类型在子类中进行定义。

d.可见性修饰符的使用
关键字private和public表示是否可以从类外访问这些数据域。私有成员只能在类内访问,而共有成员可以被其他类访问。

如果允许子类访问定义在父类中的数据域和方法,但不允许非子类访问这些数据域和方法。可以使用关键字protected完成该功能。父类中被保护的数据域或方法可以再它的子类中访问。

它们的可见性可有下表做一个简洁的归纳显示。



使用场景可分为如下几种:

1)如果不像从类外使用类的成员,就把成员声明为private;
2)如果想让该类的用户都能使用类的成员,就把成员声明为public;
3)如果想让该类的扩展者使用数据域和方法,而不想让该类的用户使用,则把成员声明为protected。
4)private和protected只能用于类的成员,而public和默认修饰符即可用于类成员,也可用于类。一个没有修饰符的类(即非公共类)是不能被其他包中的类访问的。
e.防止扩展和覆盖的办法

有时候,可能希望防止类扩展。在这种情况下,使用final修饰符表明一个类是终极的,是不能作为父类的。Math类就是一个终极类。String、StringBuilder和StringBuffer类也可以是终极类。
最后,继承和多态在Java中应用灵活多变,所以必须是重点学习的内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: