您的位置:首页 > 编程语言 > Java开发

Java 多态的详解

2016-07-17 11:39 411 查看
1.什么是多态?

一个对象的多种状态

比如:

教师 a =老钟;

员工 b= 老钟;

2.多态体现

(1)Father类

非静态成员变量x

静态成员变量y

非静态方法eat,方法体输出父类信息

静态方法speak();方法体输出父类信息

(2):Son类

非静态成员变量x

静态成员变量y

非静态方法eat,方法体输出子类信息

静态方法speak();方法体输出子类信息

class Father {
int x = 1;
static int y = 2;

void eat() {
System.out.println("开吃");
}

static void speak() {
System.out.println("小头爸爸");
}
}

class Son extends Father {
int x = 3;
static int y = 4;

void eat() {
System.out.println("大头儿子很能吃");
}

static void speak() {
System.out.println("大头儿子。");
}
}

class Demo {

public static void main(String[] args) {

Father f = new Son(); // 父类引用指向了子类对象。
System.out.println(f.x);
System.out.println(f.y);

f.eat();

f.speak();

}
}


Son类继承父类

1:创建Father f=new Son();

这就是父类引用指向了子类对象。

想想下列问题:

问f.x=?(非静态) --1

问f.y=?(静态) --2

问f.eat()输出的是子类还是父类信息?(非静态)----子类

问f.speak()输出的是子类还是父类信息?(静态)----父类

运行效果如图:



那为什么会有这样的结果呢?看下面的总结~

3.总结:

(1)当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量

(2)当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量

所以:父类和子类有相同的成员变量,多态下访问的是父类的成员变量。

(3)当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法。

(4)当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。

4.多态体现-总结:

(1)父类引用变量指向了子类的对象

(2)父类引用也可以接受自己的子类对象

5.多态前提:

类与类之间有关系,继承或者实现

6.多态弊端

提高扩展性,但是只能使用父类引用指向父类成员。

7.多态特点

非静态

(1)编译时期,参考引用型变量所属的类是否有调用的方法,如果有编译通过。没有编译失败

(2)运行时期,参考对象所属类中是否有调用的方法。

(3)总之成员函数在多态调用时,编译看左边,运行看右边。

在多态中,成员变量的特点,无论编译和运行参考左边(引用型变量所属的类)。

在多态中,静态成员函数特点,无论编译和运行都参考左边

8.多态的作用
(1)多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。

/*    1:定义功能,根据输出任何图形的面积和周长。
子类重写了父类的抽象方法,多态下,会执行子类的非静态方法。
2:多态可以作为返回值类型。
获取任意一辆车对象
3:抽象类和接口都可以作为多态中的父类引用类型。
*/
abstract class MyShape{
public abstract double getArea();
public abstract double getLen();
}
class  Rect extends MyShape{
double width ;
double height;
Rect(){

}
Rect(double width ,double height){
this.width=width;
this.height=height;
}
public double getArea(){
return width*height;
}
public  double getLen(){
return 2*(width+height);
}

}
class Circle extends MyShape{
double r;
public static final double PI=3.14;

Circle(){

}

Circle(double r){
this.r=r;
}
public double getLen(){
return 2*PI*r;
}

public double getArea(){
return PI*r*r;
}
}

class Demo{

public static void main(String[] args){

System.out.println();

print(new Rect(3,4)); //MyShape m =new Rect(3,4);

print(new Circle(3));

}

//根据用户传入的图形对象,计算出该图形的面积和周长
//1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。
public static void print(MyShape m){
System.out.println(m.getLen());
System.out.println(m.getArea());
}
}
效果图:



(2)多态可以作为返回值类型

/*获取任意一辆车对象
1:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。
2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。
Math 类
2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。
6:调用该方法,发现多态的好处。
*/
class Car {
String name;
String color;

Car() {

}

Car(String name, String color) {
this.name = name;
this.color = color;
}

void run() {
System.out.println("跑跑。。。。");
}
}

class Bmw extends Car {
Bmw() {

}

Bmw(String name, String color) {
super(name, color);
}

void run() {
System.out.println("宝马很拉风。。。。");
}
}

class Benz extends Car {
Benz() {

}

Benz(String name, String color) {
super(name, color);
}

void run() {
System.out.println("奔驰商务首选。。。。");
}
}

class Bsj extends Car {

Bsj() {

}

Bsj(String name, String color) {
super(name, color);
}

void run() {
System.out.println("泡妞首选。。。。");
}
}

class Demo {

public static void main(String[] args) {

int x = 0;
while (x < 100) {
Car c = CarFactory();
c.run();
x++;
}

}

// 定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
// 使用随机数,0.1.2 if 0 bsj 1 bmw 2 bc
public static Car CarFactory() {
int x = (int) Math.round(Math.random() * 2);

if (0 == x) {
return new Bmw("宝马x6", "红色");
} else if (1 == x) {
return new Benz("奔驰", "黑色");
} else if (2 == x) {
return new Bsj("保时捷", "棕色");
} else {
return new Benz("Smart", "红色");
}

}
}
效果图:



(3)抽象类和接口都可以作为多态中的父类引用类型。

看第一个作用的例子~

9.多态类型转换

如何在多态下,使用父类引用调用子类特有方法。

(1)基本类型转换:

自动:小->大

强制:大->小

(2)类类型转换

前提:继承,必须有关系

自动:子类转父类

强转:父类转子类

class Father {

void method1() {
System.out.println("这是父类1");
}

void method2() {
System.out.println("这是父类2");
}
}

class Son extends Father {
void method1() {
System.out.println("这是子类1");
}

void method3() {
System.out.println("这是子类3");
}
}

class Demo {

public static void main(String[] args) {
Father f = new Son();
f.method1(); // 这是子类1
f.method2(); // 这是父类2

// f.method3(); //编译报错。
// 多态弊端,只能使用父类引用指向父类成员。

// 类类型转换
Son s = (Son) f;
s.method3();

System.out.println();
}
}
效果图:



好了,多态就写完了~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多态 对象 java class