在上一篇的文章面向对象我们已经了解了什么是面向对象以及其特征,在这里我们相继的讲解一下面向对象程序设计中的两个重要的特征,也就是继承和多态
继承
继承是允许从现有的类中派生出新的类,可以对现有的类进行功能的扩充。派生出来的类可以继承已有类的属性和方法,在此基础上还可以在新类中添加一些新的属性和方法,以满足新的需求。继承是代码重用的主要表现!
public class Person { //定义父类
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void make(){
System.out.println("赚钱养家");
}
}
public class Student extends Person { //定义子类继承父类
private String school;
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public static void main(String[] args) {
Student stu = new Student();
stu.setName("张三"); //子类中没有定义,访问父类的方法
stu.setAge(18); //子类中没有定义,访问父类的方法
stu.setSchool("清华大学"); //子类定义,访问子类的方法
stu.make(); //子类中没有定义,访问父类的方法
System.out.println("我叫"+stu.getName()+","+"今年"+stu.getAge()+"就读于"+stu.getSchool());
}
}
赚钱养家
我叫张三,今年18就读于清华大学
以上程序,子类扩充了父类,增加了school的属性以及get和set方法,从上面发现可以子类继承了父类的很多属性和方法,虽然不能继承父类的私有属性和方法,但是可以通过父类的getter和setter方法获取父类的私有属性,这是子类和父类在同一包下面的情况。 如果子类和父类不再同一包下,那么子类只可以访问父类的protected和public的属性和方法,不能访问父类的private级别的属性和方法,(protected是可以跨包访问的)
重写父类的方法
class Father {
public void make(){
System.out.println("父亲负责赚钱养家");
}
}
class Son extends Father{
public void make(){ //重写父类的方法
System.out.println("儿子负责败家");
}
}
public class Demo{
public static void main(String[] args) {
Son s = new Son();
s.make(); //子类已经重写了父类的方法,则访问子类自己的方法
}
}
儿子负责败家
从上面这个程序中可以看出来当父类方法被重写后,子类或子类对象调用的是被重写后的方法。但父类或父类对象还是可以调用自己已被重写的方的。只需要把上面的 Son s = new Son(); 修改为 Father s = new Father();即可
方法重写必须所满足条件
- 子类方法的方法名,返回类型和参数必须和父类的一模一样
- 子类方法不能缩小父类方法的访问权限
- 父类的静态方法不能被子类重写
- 子类方法不能抛出比父类更多的异常
- 父类的构造方法不能被重写,但是在继承中,子类对象在实例化之前必须先调用父类中的构造方法,再调用子类的构造方法
class Father {
public Father() {
System.out.println("爸爸的构造方法");
}
}
class Son extends Father{
public Son() {
System.out.println("儿子的构造方法");
}
}
public class Demo{
public static void main(String[] args) {
Son s = new Son();
}
}
爸爸的构造方法
儿子的构造方法
转型
多态是面向对象中最灵活的机制,不但可以增加程序的扩展性,还可以提高代码的可读性。多态是依赖继承的,甚至说多态是继承的扩展
向上转型(格式为:父类 父类对象名 = new 子类();)
向上转型是指子类对象到父类对象的类型转换,使父类对象可以调用被子类重写的方法。并且向上转型是系统自动完成的,是子类对象赋值给父类对象的引用,体现的是面向对象设计中“面向抽象编程的原则”
class Father {
public void make() {
System.out.println("爸爸的make方法");
}
}
class Son extends Father{
public void make() {
System.out.println("儿子的make方法");
}
public void baijia() {
System.out.println("儿子的败家方法");
}
}
public class Demo{
public static void main(String[] args) {
Father f = new Son(); //子类向上转型为父类
f.make(); //转型后可以访问子类重写父类的make方法
}
}
儿子的make方法
上面的这个程序
Father f = new Son();将子类创建的Son对象向上转型为父类Father类型,然后再调用子类重写父类的make方法。
但是你要记住,向上转型的对象不能调用子类新增的方法,比如上面子类的baijia()方法,否则编译报错!!如果需要调用那么就必须通过Son的实例了。
向下转型
class Father {
public void make() {
System.out.println("爸爸的make方法");
}
public void say() {
System.out.println("爸爸的say方法");
}
}
class Son extends Father{
public void make() {
System.out.println("儿子的make方法");
}
public void baijia() {
System.out.println("儿子的败家方法");
}
}
public class Demo{
public static void main(String[] args) {
Father f = new Son(); //子类向上转型为父类
Son s = (Son) f; //将向上转型的父类对象向下转型为子类对象
s.make(); //调用子类的make方法
s.say(); //调用父类的say方法
s.baijia(); //调用子类的baijia方法
}
}
儿子的make方法
爸爸的say方法
儿子的败家方法
在
Son s = (Son) f;中强制把f转换为子类对象s实现向下转型,这样就可以调用子类的方了
。
切记,不能直接将父类对象向下转换为子类对象。比如 像Son s = new Father()这种萌萌操作。。。。 在进行对象的向下转型前,必须先发生对象的向上转型,否则会闹笑话的-.- 为了避免向下转型出错,可以通过instanceof关键字判断父类对象是否能转换为子类对象