java 继承 多态
继承与多态是面向对象的语言的两个重要的特点,深入的认识对运用好这门编程语言非常重要。
今天的内容包括两部分,概念整理和代码分析。
现附上一段今天写的代码,因为对这部分不满意,之后会填坑重写。
import java.util.ArrayList;
class Man{
private String name;
private Boolean sex;
private long num;
Man(String name,Boolean sex,long num){
this.name = name;
this.sex = sex;
this.num = num;
}
String getstuname(){return name;}
Boolean getSex(){return sex;};
long getNum(){return num;};
}
/**
* 目标是构建一个Manlist类,该类是一个数组类,通过继承ArrayList使其成为一个动态数组,能够非常便捷的完成增删查改的功能
*/
class Manlist extends ArrayList{
protected ArrayList<Man> list;
Manlist(int n){
list = new ArrayList<Man>(n);
}
Manlist(int n,Man[] list1){
list = new ArrayList<Man>(n);
for(int i = 0;i<list1.length;i++)
list.add(list1[i]);
}
void addMember(Man m){
add(m);
}
//对get函数进行重载,满足其搜索姓名的要求
Man get(String name){
int flag = 0;
int k = 0;
for(int i=0;i<list.size();i++){
Boolean identify = list.get(i).getstuname().equals(name);
if(identify){
flag = 1;
k = i;
break;
}
}
if(flag == 1)
return list.get(k);
else
return null;
}
Man modifyNum(long No){
int flag = 0;
int k = 0;
for(int i=0;i<list.size();i++){
if(list.get(i).getNum() == No){
flag = 1;
k = i;
break;
}
}
if(flag == 1)
return list.get(k);
else
return null;
}
void deleteMember(String name){
int i;
for(i = 0;i<list.size();i++){
String stuname = list.get(i).getstuname();
if(stuname.equals(name))
break;
}
list.remove(i);
}
void addMember(Man m,int n){
list.add(n,m);
/**
* 第一次运行报错Index: 8, Size: 0说明动态数组arraylist在此前都没有被调用
*/
}
void printGroup(){
for(int i = 0;i<list.size();i++){
System.out.println("Name: "+ list.get(i).getstuname()+"\tsex: "+ list.get(i).getSex()+ "\tNum: "+list.get(i).getNum());
}
}
}
继承的概念
类之间的继承关系是面向对象的设计语言的基本特征。
同类事物具有共同性,在同类事物中,每个事物又具有其特殊性。
通过抽象原则舍去对象的特殊性,抽取其共同性,则得到一个适用于一批对象的类,这就是一般类,而具有特殊性的类别称为特殊类。
通过继承原则,一般类具有一般类和特殊类共同的属性和操作,这些在一般类中显式的定义出来,在特殊类中不必重复定义。
特殊类的对象则拥有一般类的全部或部分(private除外)属性和方法,即特殊类对一般类的继承。
定义子类
java子类对父类的继承使用extends语句。每个类只能与有一个父类。如果需要使用多个父类的方法,可以通过接口调用。
class cl extends cl2{
....
}
隐藏属性
子类默认具有父类privat以外的数据成员,但是可以通过在子类申明同名的数据成员,将父类的数据成员隐藏起来。数据成员(属性)的隐藏意味着父类的数据成员依然在,可以通过super
进行访问。
//SubclassHideDemo.java
class A1{
int a1;
A1(){
a1 = 5;
}
}
class A2 extends A1{
int a1 = 10;
int show1(){return a1;}
int show2(){return super.a1;};
}
public class SubclassHideDemo{
public static void main(String args[]){
A2 ob = new A2();
System.out.println(ob.show1() + "\t" + ob.show2());
}
}
结果:
10 5
覆盖方法
子类默认具有父类的非私有方法,可以直接调用。同时,子类可以构造和父类数据类型,方法名,形参完全相同,而方法体不同的方法对父类的方法进行覆盖。覆盖顾名思义会将父类方法从内存抹去,父类方法在子类对象中不再存在,但是子类方法中可以通过super
调用父类被覆盖的方法。
//SubclassCoverDemo.java
package com;
class A1{
int a1 = 5;
int b1 = 10;
void print1(){
System.out.println(a1);
}
void print2(){
System.out.println(b1);
}
}
class A2 extends A1{
int a2 = 6;
int b2 = 11;
void print1(){
System.out.println(a2);
}
void print3(){
super.print2();
}
}
public class SubclassCoverDemo{
public static void main(String args[]){
A2 ob = new A2();
ob.print1(); //父类方法被覆盖
ob.print2(); //使用父类方法
ob.print3(); //子类方法中通过super调用了父类被覆盖的方法
}
}
结果:
6
10
10
super和this的用法
在上一节中我们两次使用了super
这个修饰在子类中使用父类的成员和方法,这里对this和super做一个归纳。
- this
this指向当前的对象自身,使用this标识当前对象的成员和方法,可以提高程序的清晰性,减少重名导致的错误。
- 用来访问当前对象的数据成员
- 用来访问当前对象的成员方法
- 当有重载的构造方法时,用来引用同类的其他构造方法
- super
super指向当前对象的直接父类,当父类的成员和方法被隐藏和覆盖,而需要引用他们时,可以通过super实现。
- 访问直接父类被隐藏的数据成员
- 调用直接父类被覆盖的成员方法
- 调用直接父类的构造方法。
多态的概念
通过方法的重名现象提高代码的抽象性和简洁性。多态包括两个层次,同一类下同一方法名的不同形参的使用方式——重载,和父子类下同一方法名的相同形参的使用方式——覆盖(见上一节)。
重载方法
重载方法是在同一类里对相同方法的不用使用形式,重载要求方法的数据类型和方法名完全相同但是形参不相同,形参的不同表现在参数的个数,数据类型和顺序。
//Overload.java
package com;
class F{
int i = 0;
int j = 0;
int k = 0;
F(int i){
this.i = i;
}
F(int i,int j){
this(i); //通过this调用本类的构造方法
this.j = j;
}
F(int i,int j,int k){
this(i,j);
this.k = k;
}
void Fprint(){
System.out.println("i = " + i+ " j = " + j + " k = " + k);
}
}
public class Overload{
public static void main(String args[]){
F f1 = new F(5);
F f2 = new F(5,6);
F f3 = new F(5,6,7);
f1.Fprint();
f2.Fprint();
f3.Fprint();
}
}
结果:
i = 5 j = 0 k = 0
i = 5 j = 6 k = 0
i = 5 j = 6 k = 7