父类引用指向子类对象

最近学习装饰者模式的时候经常用到这个概念:

假如我们有一个父类Coffee 还有一个它的子类Suger那么我们将 Coffee coffee=new suger()就叫做父类引用指向子类对象;

总结一下它的特点吧:

1.子类suger对于父类的函数重写当使用父类coffee的时候会使用重写过后的函数

2.子类对于父类的重载函数使用父类引用的时候不能用,也就是只能用到父类引用里面定义有的函数

3.子类对于父类里面的变量假如重新赋值的话使用父类引用指向子类对象的话,coffee里面的变量也会变

还有就是再顺带总结一下父类以及子类的强制类型转换:(对于接口的操作与继承的关系是一样的)

          *父类强制转换成子类在编译的时候不会报错但是运行的时候回抛出异常不能进行类型转换
         * 在内存层面就是父类的内存空间小不能转化成内存空间更大的子类
         * 但是子类可以转化成内存小的父类,转化是指的 大的部分也就是自己加上的方法不能用,但是还可以再
         * 从父类转化成子类,此时就可以使用子类的方法了

下面就以代码的形式做一下总结:

//先定义一个接口
package test1;

public interface Coffee {
   public  int price=12;
   public void func1();
   public void func2();
}
//================定义父类
package test1;

public class Suger implements Coffee {

    private int price2=2;
    private int o=33;
    private int weight2=4;
	@Override
	public void func1() {
		System.out.println("func1");
	}

	@Override
	public void func2() {
		System.out.println("price是"+price2+"         weight是"+weight2);

	}
	public void func3() {
		System.out.println("func3");

	}
	public static void main(String[] args) {
		Coffee coff=new Suger();//接口亦可以定义成父类引用的形式   在装饰者模式里面用到很多
		Suger sug=new Suger();
		Coffee coff2=(Coffee)sug;
		coff2.func1();
		Suger sug2=(Suger)coff2;
		sug2.func2();
		System.out.println("========上面是对于强制类型转换的操作");
		//接口的操作与继承的操作在这里都一样
		sug.func2();
		
		sug.func3();
		coff.func1();
		
		//coff.func3();
	}

    }
//========================定义子类=============================================
package test1;

public class Test extends Suger {
	
	 private int price2=5;
	
	 private int weight2=6;
	

	@Override
	public void func1() {
		super.func1();
	}

	@Override
	public void func2() {
		System.out.println("price是"+price2+"   weight是"+weight2);
	}
	
    //重载
	public void func3(int i) {
		System.out.println(i);
	}
	public void func4() {
		System.out.println("func4");
	}

	public static void main(String[] args) {
		//==========子类强制转换成父类对象还可以强制转换回子类对象
		Test test=new Test();
		Suger suger=(Suger)test;
		//suger.func4();// 强转过后子类独有的方法不能用了
		Test test2=(Test)suger;
		test2.func4(); 
		System.out.println("========================================");
		/*
		 * 父类强制转换成子类在编译的时候不会报错但是运行的时候回抛出异常不能进行类型转换
		 * 在内存层面就是父类的内存空间小不能转化成内存空间更大的子类
		 * 但是子类可以转化成内存小的父类,转化是指的 大的部分也就是自己加上的方法不能用,但是还可以再
		 * 从父类转化成子类,此时就可以使用子类的方法了
		 *  Exception in thread "main" func4
			java.lang.ClassCastException: test1.Suger cannot be cast to test1.Test
		    at test1.Test.main(Test.java:39)
		 */
		//Suger suger11=new Suger();
		//Test test3=(Test)suger11;
		//Suger suger12=(Suger)test3;
		//test3.func4();
		//suger11.func4();错误
		Suger sug=new Test();
		Test tes=new Test();
		sug.func1();
		sug.func2();//方法二进行过重载
		sug.func3();
		//sug.func3(666);错误因为在父类里面没有定义
		//sug.func4();
		System.out.println("============================tes===========================================");
		tes.func1();
		tes.func2();
		tes.func3(100000);
		tes.func4();
		
		//System.out.println(o);//private不可见
	}

}

输出结果:

        父类Suger:

func1
price是2         weight是4
========上面是对于强制类型转换的操作
price是2         weight是4
func3
func1

      子类Test:

func4
========================================
func1
price是5   weight是6
func3
============================tes===========================================
func1
price是5   weight是6
100000
func4

 

### 父类引用指向子类对象的用法与原理 在Java中,父类引用指向子类对象是一种实现多态的重要机制。这种机制的核心在于继承、方法重写以及向上转型[^1]。通过这种方式,程序可以更加灵活地处理不同类型的对象。 #### 原理分析 1. **继承关系**:子类继承父类后,会自动获得父类的所有非私有属性和方法。这是多态的基础条件之一。 2. **方法重写**:子类可以通过重写父类的方法来改变其行为。当父类引用指向子类对象时,调用的方法是子类中重写的方法,而不是父类中的方法[^2]。 3. **向上转型**:在Java中,父类引用可以直接指向子类对象,这种现象称为向上转型。编译器会将子类实例视为父类类型,从而实现多态性[^4]。 #### 示例代码 以下是一个简单的示例,展示如何使用父类引用指向子类对象并实现多态: ```java // 定义父类 class Animal { public void sound() { System.out.println("动物发出声音"); } } // 定义子类1 class Cat extends Animal { @Override public void sound() { System.out.println("喵喵喵"); } } // 定义子类2 class Dog extends Animal { @Override public void sound() { System.out.println("汪汪汪"); } // 子类特有的方法 public void wagTail() { System.out.println("摇尾巴"); } } public class Main { public static void main(String[] args) { // 父类引用指向子类对象 Animal animal1 = new Cat(); Animal animal2 = new Dog(); // 调用的是子类重写的方法 animal1.sound(); // 输出: 喵喵喵 animal2.sound(); // 输出: 汪汪汪 // 如果需要访问子类特有方法,必须进行强制类型转换 ((Dog) animal2).wagTail(); // 输出: 摇尾巴 } } ``` #### 注意事项 - 父类引用无法直接访问子类特有的方法。如果需要访问这些方法,必须通过强制类型转换来实现[^3]。 - 在运行时,JVM会根据实际对象的类型来决定调用哪个方法。这就是动态绑定(Dynamic Binding)的工作方式。 ### 总结 父类引用指向子类对象是Java中实现多态的关键机制。它允许程序以统一的方式处理不同类型的对象,同时通过动态绑定确保调用的是子类中重写的方法。这种设计不仅提高了代码的灵活性,还增强了可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值