什么是多态?
将一个方法调用同一个方法主体关联起来叫做绑定。若在程序执行前进行绑定,叫做前期绑定。
多态也称作动态绑定、后期绑定或者运行时绑定。是指在运行时根据对象的类型进行绑定。多态是继数据抽象和继承之后的第三种基本特征。
多态的作用是什么?
多态的作用是消除类型之间的耦合关系。多态通过分离做什么和怎么做,从另一角度将接口和实现分离开来。多态带来很多成效:更快的程序开发过程、更好的代码组织、更好扩展的程序以及更容易的代码维护等。
实例如下:Text0520.java
enum Note{//向上转型:把对某个对象的引用当做对其基类型的引用。
MIDDLE_C,C_SHARP,B_FLAT;
}
class Instrument{
void play(Note n){System.out.println("Instrument.play()");}
}
class Wind extends Instrument{
void play(Note n){System.out.println("Wind.play() "+n);}
}
class Music{
static void tune(Instrument i){i.play(Note.MIDDLE_C);}
public static void main(String[] args){
Wind aWind=new Wind();
tune(aWind);//tune()接受一个Instrument引用,也接受Instrument的任何导出类。
}
}
public class Test0520{
public static void main(String[] args){Music.main(args);}
}
import java.util.Random;//多态是指在运行时根据对象的类型进行绑定。因此静态方法不具有多态性。
class Shape{
void draw(){}
void erase(){}
}
class Circle extends Shape{
void draw(){System.out.println("Circle.draw()");}
void erase(){System.out.println("Circle.erase()");}
}
class Square extends Shape{
void draw(){System.out.println("Square.draw()");}
void erase(){System.out.println("Square.erase()");}
}
class Triangle extends Shape{
void draw(){System.out.println("Triangle.draw()");}
void erase(){System.out.println("Triangle.erase()");}
}
class RandomShape{
private Random rand=new Random(47);
Shape next(){
switch(rand.nextInt(3)){
default:
case 0:return new Circle();
case 1:return new Square();
case 2:return new Triangle();
}
}
}
class Shapes{
private static RandomShape rs=new RandomShape();
public static void main(String[] args){
Shape[] s=new Shape[5];
for(int i=0;i<s.length;i++){
s[i]=rs.next();
}
for(Shape shape:s){//在编译时,编译器不需要获得任何特殊信息就能正确调用
shape.draw();//对draw()方法的调用都是通过动态绑定进行的。
}
}
}
public class Test0520{
public static void main(String[] args){Shapes.main(args);}
}
enum Note{//多态使程序更好扩展,将改变的事物与不变的事物分离开来
MIDDLE_C,C_SHARP,B_FLAT;
}
class Instrument{
void play(Note n){System.out.println("Instrument.play() "+n);}
String what(){return "Instrument";}
void adjust(){System.out.println("Adjusting Instrument");}
}
class Wind extends Instrument{
void play(Note n){System.out.println("Wind.play() "+n);}
String what(){return "Wind";}
void adjust(){System.out.println("Adjusting Wind");}
}
class Percussion extends Instrument{
void play(Note n){System.out.println("Percussion.play() "+n);}
String what(){return "Percussion";}
void adjust(){System.out.println("Adjusting Percussion");}
}
class Brass extends Wind{
void play(Note n){System.out.println("Brass.play() "+n);}
void adjust(){System.out.println("Adjusting Brass");}
}
class WoodWind extends Wind{
void play(Note n){System.out.println("WoodWind.play() "+n);}
String what(){return "WoodWind";}
}
class Music{
static void tune(Instrument i){//tune()方法不需要编译就能和所有新类新方法一起正确运行。
i.play(Note.MIDDLE_C);
}
static void tuneAll(Instrument[] e){
for(Instrument i:e){tune(i);}
}
public static void main(String[] args){
Instrument[] ins={new Wind(),new Percussion(),new Brass(),new WoodWind()};
tuneAll(ins);
}
}
public class Test0520{
public static void main(String[] args){Music.main(args);}
}
-------------------------------------------------------------
E:\java>java Test0520
Wind.play() MIDDLE_C
Percussion.play() MIDDLE_C
Brass.play() MIDDLE_C
WoodWind.play() MIDDLE_C
class Meal{//继承与构造器的初始化
Meal(){System.out.println("Meal()");}
}
class Bread{
Bread(){System.out.println("Bread()");}
}
class Lunch extends Meal{
Lunch(){System.out.println("Lunch()");}
}
class PortableLunch extends Lunch{
PortableLunch(){System.out.println("PortableLunch()");}
}
class Sandwich extends PortableLunch{
private Bread b=new Bread();
public Sandwich(){System.out.println("Sandwich()");}
public static void main(String[] args){
new Sandwich();
}
}
public class Test0520{
public static void main(String[] args){Sandwich.main(args);}
}
-----------------------------------------------------------------------
E:\java>java Test0520
Meal()
Lunch()
PortableLunch()
Bread()
Sandwich()
class Glyph{//多态与构造器的初始化
void draw(){System.out.println("Glyph.draw()");}
Glyph(){//构造器准则:用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他(可以被覆盖的)方法。
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph{
private int radius=1;//1.任何方法被调用之前进行默认初始化radius=0。//3.构造器调用之前自动初始化radius=1
void draw(){System.out.println("RoundGlyph.draw(),radius = "+radius);}//2.调用覆盖方法
RoundGlyph(int i){//4.调用构造器
radius=i;
System.out.println("RoundGlyph(),radius = "+radius);
}
}
public class Test0520{
public static void main(String[] args){
new RoundGlyph(5);
}
}
-------------------------------------------------
E:\java>java Test0520
Glyph() before draw()
RoundGlyph.draw(),radius = 0
Glyph() after draw()
RoundGlyph(),radius = 5
//协变返回类型:在导出类中进行覆盖的方法,可以返回基类被覆盖方法返回类型的某种导出类型
class Grain{public String toString(){return "Grain";}}//Grain基类
class Wheat extends Grain{public String toString(){return "Wheat";}}//Grain导出类
class Mill{Grain process(){return new Grain();}}//Mill基类返回Grain基类
class WheatMill extends Mill{Wheat process(){return new Wheat();}}//Mill导出类返回Grain基类的导出类型
public class Test0520{
public static void main(String[] args){
Mill m=new Mill();
Grain g=m.process();
System.out.println(g);
m=new WheatMill();
g=m.process();
System.out.println(g);
}
}
----------------------------------
E:\java>java Test0520
Grain
Wheat
class Actor{void act(){}}//继承设计准则:用继承表达行为间的差异,用字段(组合)表达状态上的变化。
class HappyActor extends Actor{
void act(){System.out.println("HappyActor");}
}
class SadActor extends Actor{
void act(){System.out.println("SadActor");}
}
class Stage{
private Actor actor=new HappyActor();
void change(){actor=new SadActor();}
void performPlay(){actor.act();}
}
public class Test0520{
public static void main(String[] args){
Stage stage=new Stage();
stage.performPlay();
stage.change();
stage.performPlay();
}
}
---------------------------------------------
E:\java>java Test0520
HappyActor
SadActor
class Useful{//向下转型与运行时类型识别(RTTI)
void f(){System.out.println("Useful.f()");}
void g(){System.out.println("Useful.g()");}
}
class MoreUseful extends Useful{
void f(){System.out.println("MoreUseful.f()");}
void g(){System.out.println("MoreUseful.g()");}
void h(){System.out.println("MoreUseful.h()");}
}
public class Test0520{//RTTI:在运行期间对类型进行检查的行为。
public static void main(String[] args){
Useful[] x={new Useful(),new MoreUseful()};
x[0].f();
x[1].g();//向上转型
//向上转型会丢失具体的类型信息
//x[1].h();//错误:Useful找不到方法h()
//RTTI对类型进行检查,确保类型正确,否则返回异常
((MoreUseful)x[1]).h();//向下转型成功,可以获取类型信息
((MoreUseful)x[0]).h();//转型失败,返回一个ClassCastException类转型异常
}
}
--------------------------------------------------
E:\java>java Test0520
Useful.f()
MoreUseful.g()
MoreUseful.h()
Exception in thread "main" java.lang.ClassCastException: Useful cannot be cast t
o MoreUseful
at Test0520.main(Test0520.java:196)