zoukankan      html  css  js  c++  java
  • Java 多态透析 详细理解

    1:什么是多态

           一个对象的多种状态

           (老师)(员工)(儿子)

           教师 a =老钟;

           员工 b =老钟;

    2:多态体现

      父类引用变量指向了子类的对象          Father f = new Son();

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

         1:Father类

               1:非静态成员变量x

               2:静态成员变量y

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

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

    class Father {
    	int x = 1;
    	static int y = 2;
    
    	void eat() {
    		System.out.println("开吃");
    	}
    
    	static void speak() {
    		System.out.println("小头爸爸");
    	}
    }
    

           2:Son类

               1:非静态成员变量x

               2:静态成员变量y

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

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

    class Son extends Father {
    	int x = 3;
    	static int y = 4;
    
    	void eat() {
    		System.out.println("大头儿子很能吃");
    	}
    
    	static void speak() {
    		System.out.println("大头儿子。");
    	}
    }
    
    class Demo1 {
    
    	public static void main(String[] args) {
    
    		Father f = new Son(); // 父类引用指向了子类对象。
    		System.out.println(f.x); // 1
    		System.out.println(f.y); // 2
    		f.eat(); // 输出的是子类的。
    		f.speak(); // 输出的是父类
    		
    	}
    }
    

      3总结:

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

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

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

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

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

    多态前提

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

    多态弊端

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

    多态特点

        非静态

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

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

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

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

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

    多态练习

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

           1:定义功能,根据输出任何图形的面积和周长。

    abstract class MyShape{
    	public abstract double getArea();
    	public abstract double getLen();
    }
    

           2:定义Rect类继承MyShape

    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);
    	}
    }
    

           3:定义Cricle类继承MyShape

    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;
    	 }
    }
    

           4:定义静态方法计算任意图形的面积和周长

               1:未知内容参与运算,不能确定用户传入何种图形,使用多态。

                  1:形参定义为 MyShape my

               2:调用计算面积方法,和计算周长方法。并打印

                  2:使用多态特性,子类重写了父类非静态方法,会执行子类的方法。

    class Demo2{
    	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:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。

    class Car {
    	String name;
    	String color;
    	Car() {
    	}
    	Car(String name, String color) {
    		this.name = name;
    		this.color = color;
    	}
    	void run() {
    		System.out.println("跑跑。。。。");
    	}
    }
    

        2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

    class Bmw extends Car {
    	Bmw() {
    	}
    	Bmw(String name, String color) {
    		super(name, color);
    	}
    	void run() {
    		System.out.println("宝马很拉风。。。。");
    	}
    }
    

        3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

    class Benz extends Car {
    	Benz() {
    	}
    	Benz(String name, String color) {
    		super(name, color);
    	}
    	void run() {
    		System.out.println("奔驰商务首选。。。。");
    	}
    }
    

        4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

    class Bsj extends Car {
    	Bsj() {
    	}
    	Bsj(String name, String color) {
    		super(name, color);
    	}
    	void run() {
    		System.out.println("泡妞首选。。。。");
    	}
    }
    

               5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。

                  1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。

                  2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。

    class Demo3 {
    	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:抽象类和接口都可以作为多态中的父类引用类型。 多态之类型转型

    1:案例定义Father类

           1:定义method1和method2方法

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

        2:定义Son类继承Father类

           1:定义method1(重写父类method1)和method2方法

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

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

           1: f.method1() 调用的子类或者父类?

           2: f.method2() 编译和运行是否通过?

           3: f.method3() 编译和运行是否通过?(编译报错)

    class Demo4 {
    	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();
    	}
    }
    

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

           1:基本类型转换:

               1:自动:小->大

               2:强制:大->小

           2:类类型转换

               前提:继承,必须有关系

               1:自动:子类转父类

               2:强转:父类转子类

               3:类型转换

                  1:Son s=(Son)f

                  2:s.method3();

    案例:

          1:定义Animal类颜色成员变量,无参构造,有参构造,run方法

    class Animal {
    	String color;
    	Animal() {
    	}
    	Animal(String color) {
    		this.color = color;
    	}
    	void run() {
    		System.out.println("跑跑");
    	}
    }

      2:定义Dog类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Dog的特有方法ProtectHome

    class Dog extends Animal {
    	Dog() {
    	}
    	Dog(String color) {
    		super(color);
    	}
    	void run() {
    		System.out.println("狗儿跑跑");
    	}
    	void protectHome() {
    		System.out.println("旺旺,看家");
    	}
    }
    

      3:定义Fish类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Fish特有方法swim

    class Fish extends Animal {
    	Fish() {
    	}
    	Fish(String color) {
    		super(color);
    	}
    	void run() {
    		System.out.println("鱼儿水中游");
    	}
    	void swim() {
    		System.out.println("鱼儿游泳");
    	}
    }
    

         4:使用多态,Animal a=new Dog();

         5:调用Dog的特有方法,ProtectHome

           1:类类型转换,Dog d=(Dog)a;

           2:d.protectHome

    class Demo5 {
    
    	public static void main(String[] args) {
    
    		Animal ani = new Dog();
    		// ani.protectHome();
    		// 正常转换
    		Dog d = (Dog) ani;
    		d.protectHome();
    
    		// 多态例外
    		Animal an = new Animal();
    		// ClassCastException
    		// Dog d=(Dog)an
    
    		// 多态例外
    		Animal dog = new Dog();
    		// ClassCastException
    		// Fish f = (Fish) dog;
    
    	}
    }
    

        6:非多态

        1:Animal a=new Animal();

           2:类类型转换

               Dog d=(Dog)a; 

               d.protectHome();

            3:编译通过,运行出现异常

               1:ClassCastException

        7:多态例外

               1:Animal  a=new Dog();

               2:类类型转换

                  1:Fish f=(Fish)a;

                  2:f.fish();

                  3:编译通过,运行异常

                      1:ClassCastException

                  4:虽然是多态,但是狗不能转为鱼,他们之间没有关系。

    案例2  

        1:定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法

        2:使用多态,方法形参,不能确定用户传入的是那种动物

        3:使用instanceof 关键字,判断具体是何种动物,

        4:类转换,执行该动物的特有方法。

    class Animal {
    	String color;
    	Animal() {
    	}
    	Animal(String color) {
    		this.color = color;
    	}
    	void run() {
    		System.out.println("跑跑");
    	}
    }
    
    class Dog extends Animal {
    	Dog() {
    	}
    	Dog(String color) {
    		super(color);
    	}
    	void run() {
    		System.out.println("狗儿跑跑");
    	}
    	void protectHome() {
    		System.out.println("旺旺,看家");
    	}
    }
    
    class Fish extends Animal {
    	Fish() {
    	}
    	Fish(String color) {
    		super(color);
    	}
    	void run() {
    		System.out.println("鱼儿水中游");
    	}
    	void swim() {
    		System.out.println("鱼儿游泳");
    	}
    }
    
    class Bird extends Animal {
    	Bird() {
    	}
    	Bird(String color) {
    		super(color);
    	}
    	void run() {
    		System.out.println("鸟儿空中飞");
    	}
    	void fly() {
    		System.out.println("我是一只小小鸟。。。。");
    	}
    }
    
    class Demo6 {
    	public static void main(String[] args) {
    		System.out.println();
    		doSomething(new Dog());
    		doSomething(new Bird());
    		doSomething(new Fish());
    	}
    	// 定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法
    	public static void doSomething(Animal a) {
    		if (a instanceof Dog) {
    			Dog d = (Dog) a;
    			d.protectHome();
    		} else if (a instanceof Fish) {
    			Fish f = (Fish) a;
    			f.swim();
    		} else if (a instanceof Bird) {
    			Bird b = (Bird) a;
    			b.fly();
    		} else {
    			System.out.println("over");
    		}
    	}
    }
    
  • 相关阅读:
    __attribute__((noreturn))的用法
    selenium定位元素的方法
    zzz
    go语言的第一个helloworld
    mac eclipse 创建Java 工程
    Jmeter:图形界面压力测试工具
    使用 HAProxy, PHP, Redis 和 MySQL 轻松构建每周上亿请求Web站点
    从Log4j迁移到LogBack的理由
    SLF4J和Logback日志框架详解
    security with restful
  • 原文地址:https://www.cnblogs.com/loveincode/p/5326995.html
Copyright © 2011-2022 走看看