壹、继承关系的实现
一、基本语法
- 如何构建一个子类
/**author me
*version 1.0.0
*/
public class Person{
private String name;
private String address;
/**
*构造函数
*@param setName 设置名字
*@param setAddress 设置地址
*/
public Person(String setName,String setAddress){
name=setName;
address=setAddress;
}
/**
*@return 名字
*/
public String getName(){
return name;
}
/**
*@return 地址
*/
public String getAddress(){
return address;
}
}
父类构建好之后,就可以构造子类了
/**
*@author me
*@version 1.0.0
*/
public class Student extends Person{
private String id;
/**
*构造函数
*@param setName 设置姓名
*@param serAddress 设置地址
*@param setId; 设置学号
*/
public Student(String setName,String setAddress,String setId){
super(setName,setAddress);//这句话作用后面再解释,只要知道这里不能直接赋值
id=setId;
}
/**
*@return id
*/
public String getId(){
return id;
}
}
其实,构造一个子类,无非就是第一行在子类名字后面加个extends父类
除此以外,子类还有些性质:
①继承父类的属性和方法,后续可以调用
②即使是亲密的关系,子类仍然不能调用父类的private属性。private是只给自己用的。如果想给子类用,应当设置成protected权限或者用get方法访问
//就比如在Student类里写一个toString
//注意:下面两个我们是写在Student类里面的
...//下面的写法是错的
public String toString(){
return "name:"+name+" address:"+address+" id:"+id;
}
...//下面的写法是对的
public String toString(){
return "name:"+getName()+" address:"+getAddress()+" id:"+id;
}
即使name和address事实上也是Student的属性,但是前提是这是父类的私有属性,因此就不能直接访问。
上面super()那一行就是因此不能直接给name,address赋值
- super
(1)前面说子类继承父类所有方法和属性,但是有一点例外:子类不继承父类的构造方法,而是通过super(参数列表)来调用父类的构造方法构造自己继承的那几个属性。这一行必须是子类构造函数的第一行。
(2)如果子类构造函数里面没有写super(参数列表),编译器会自动加上一个无参的super()。如果父类没有这种无参构造方法,就会报错。
(3)前两条是关于super与构造函数,例子回头看一就行。super还可以调用父类的其他方法,让子类函数显得更简洁
//假设Person的构造函数写好了
//以及Javadoc我就不写了
//以及下面是Student的toString
public String toString(){
return super.toString()+" id:"+id;
}
这样是不是简洁多了?
- 关于构造函数要注意的两点
(1) 正式写程序的时候,创建子类对象要调用构造函数,此时如果构造函数不带参数,将先调用父类的默认构造函数,再调用子类的默认构造函数
(2) 如果父类没有构造函数,子类又创建带任意参数的对象,都会默认调用父类的默认构造函数,即使父类没有定义。
但是,如果父类有含餐的构造函数,此时就必须声明父类哪个是默认的构造函数了
二、转型
- 向上转型:子类对象可以当成父类对象来使用
Person person=new Student("tadokoro kouji","shimokitazawa","114514");
//但是,通过这个person变量,不能使用Student特有的方法,因为
//编译器认为person是Person类型,并没有子类的方法
- 向下转型:把父类强制转化为子类型的变量
向上转型永远合法,向下转型就不一定了
//合法向下转型:person事实上指向一个Student
Student student=new Student("tadokoro kouji","shimokitazawa","114514");
person person=student;
String id=((Student)person).getId();
//非法向下转型:person事实上指向一个Person
//此时抛出classCastException
Person person=new Person("tadokoro kouji","shimokitazawa");
String id=((Student)person).getId();
常用instanceof确保转型合法
//thisIsAClass instanceof Originclass
//如果thisIsAClass为Originclass类,返回true
//如果thisIsAClass为Originclass的子类,返回true
//如果thisIsAClass是null,返回false
Person person=new Student("tadokoro kouji","shimokitazawa","114514");
......
if(person instanceof Student)
{
String id=((Student)person).getId();
}
上面就可以不报错了
贰、方法覆写
一、来源
有时,父类的某个方法在子类并不完全适用,需要修改。这个时候,就可以在子类中以子类的需求再写一遍这个方法,将继承于父类的覆盖掉,因此称为“覆写”
二、要求
- 子类覆写的方法权限不能比父类的对应方法更严格。比如父类某个方法是protected,子类覆写的时候就不能把它写成private
- 父类中static以及final的方法不能覆写
- 覆写是父类与子类之间,重载是一个类之中
三、举例
首先,提供一个背景知识,Java中,有一个类:Java.lang.Object是所有类的基类(父类),它提供的方法中有两个不大适用,常常被子类修改覆写。
- euqals()
本来,这个方法是比较两个类的引用是否相等。由于我们知道类名就是地址,比较它两引用是否相等,就是比较它两指向的地址是否相等。
而有的时候我们想要比较数字是否相等,字符串是否一致,用这个equals就不大合适了。
因此,String就覆写了equals方法,想要比较两个字符串,不能用==,只能用equals
再如,比较上面写的Student对象是否相同,就要覆写一个equals比较他们的所有属性。 - toString()
Object的toString返回对象的哈希码(根据对象特征确定地一组编码),但是想要把int转化成String用这个toString就不行了,要覆写一个