共计 2275 个字符,预计需要花费 6 分钟才能阅读完成。
1、向上转型
1.1、什么是向上转型
在上图中,酒(Wine)是父类,剑南春(JNC)、五粮液(WLY)、酒鬼酒(JGJ)是子类。我们定义如下代码:
JNC a = new JNC();
对于这个代码我们非常容易理解无非就是实例化了一个剑南春的对象嘛!但是这样呢?
Wine a = new JNC();
在这里我们这样理解,这里定义了一个 Wine 类型的 a,它指向 JNC 对象实例。由于 JNC 是继承了 Wine,所以 JNC 可以自动向上转型为 Wine,所以 a 是可以指向 JNC 实例对象的。
1.2、向上转型的优缺点
这样做存在一个非常大的好处,在继承中我们知道子类是父类的扩展,它可以提供比父类更加强大的功能,如果我们定义了一个指向子类的父类引用类型,那么它除了能够引用父类的共性外,还可以使用子类强大的功能。
但是向上转型存在一些缺憾,那就是它必定会导致一些方法和属性的丢失,而导致我们不能够获取它们。所以父类类型的引用可以调用父类中定义的所有属性和方法,对于只存在与子类中的方法和属性它就望尘莫及了。
1.3、案例
// 酒类 | |
public class Wine {public void fun1(){System.out.println("Wine 的 Fun....."); | |
fun2();} | |
public void fun2(){System.out.println("Wine 的 Fun2..."); | |
} | |
} |
// 剑南春 | |
public class JNC extends Wine{/** | |
@desc 子类重载父类方法 | |
父类中不存在该方法,向上转型后,父类是不能引用该方法的 | |
@param a | |
@return void | |
*/ | |
public void fun1(String a){System.out.println("JNC 的 Fun1..."); | |
fun2();} | |
/** | |
子类重写父类方法 | |
指向子类的父类引用调用 fun2 时,必定是调用该方法 | |
*/ | |
public void fun2(){System.out.println("JNC 的 Fun2..."); | |
} | |
} |
public class WineDemo {public static void main(String[] args) {Wine a = new JNC(); | |
a.fun1();} | |
} |
运行结果:
2、多态的实现
2.1、实现多态的必要条件
** 继承:** 在多态中必须存在有继承关系的子类和父类。
** 重写:** 子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
** 向上转型:** 在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
2.2、实现多态的原则
对于 Java 而言,多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
2.3、实现形式
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。
案例:
public class Wine {private String name; | |
public String getName() {return name; | |
} | |
public void setName(String name) {this.name = name; | |
} | |
// 构造方法:产生对象、初始化成员变量 | |
// 构造方法特点:public、无返回值类型、方法名与类名相同 | |
// 每一个类都有一个默认的无参的构造方法 | |
public Wine(){ } | |
public String drink(){return "喝的是" + getName();} | |
/** | |
重写 toString() | |
*/ | |
public String toString(){return null; | |
} | |
} |
public class JNC extends Wine{// 通过构造方法初始化了,酒名 | |
public JNC(){setName("JNC"); | |
} | |
/** | |
重写父类方法,实现多态 | |
*/ | |
public String drink(){return "喝的是" + getName();} | |
/** | |
重写 toString() | |
*/ | |
public String toString(){return "Wine :" + getName();} | |
} |
public class JGJ extends Wine{public JGJ(){setName("JGJ"); | |
} | |
/** | |
重写父类方法,实现多态 | |
*/ | |
public String drink(){return "喝的是" + getName();} | |
/** | |
重写 toString() | |
*/ | |
public String toString(){return "Wine :" + getName();} | |
} |
public class WineDemo{public static void main(String[] args) {// 定义父类数组 | |
Wine[] wines = new Wine[2]; | |
// 定义两个子类 | |
JNC jnc = new JNC(); | |
JGJ jgj = new JGJ(); | |
// 父类引用子类对象 | |
wines[0] = jnc; | |
wines[1] = jgj; | |
for(int i = 0 ; i < 2 ; i++){System.out.println(wines[i].toString() + "--" + wines[i].drink()); | |
} | |
System.out.println("-------------------------------"); | |
} | |
} |
运行结果:
