【java】多态


多态

对象既可以作为它自己本身的类型使用,也可以作为它的基类型使用

在面向对象的程序设计语言中,多态是继数据抽象和继承之后的第三种特征
即:Music . tune() 方法接受一个Instrment 引用,同时也接受任何导出自Instrument的类,当然本身Music是子类,导出自Instrument类。

方法调用绑定
将一个方法调用同一个方法主体关联起来被称作绑定
包括:前期绑定 和 后期绑定(运行时根据对象的类型进行绑定,也成为动态绑定和运行时绑定)
Java中除了static方法和final方法(private方法属于final方法)之外,其他的所有方法都是后期绑定
声明final,可以“关闭”动态绑定,但是运用final要慎重。

产生正确的行为(向上转型)
package source.sunday;
import java.util.Random;
class Shape {
	public void draw() {}
	public void erase() {}
}
class Circle extends Shape {
	public void draw() { System.out.println("Circle.draw()"); }
	public void erase() { System.out.println("Circle.erase()"); }
}
class Square extends Shape {
	public void draw() { System.out.println("Square.draw()"); }
	public void erase() { System.out.println("Square.erase()"); }
}
class Triangle extends Shape {
	public void draw() { System.out.println("Triangle.draw()"); }
	public void erase() { System.out.println("Triangle.erase()"); }
}
class RandomShapeGenerator {
	private Random rand = new Random();
	public Shape next() {
		switch(rand.nextInt(3)) {
		case 0: return new Circle();
		case 1: return new Square();
		case 2: return new Triangle();
		}
		return null;
	}
}
public class Shapes {
	private static RandomShapeGenerator gen = new RandomShapeGenerator();
	public static void main(String[] args) {
		Shape[] s = new Shape[9];
		for(int i = 0; i < s.length; i++)
			s[i] = gen.next();
		for(Shape shp : s)
			shp.draw();
	}
}
RandomShapeGenerator类似一个工厂,通过随机方式生成shape对象。
output:


域和静态方法,不存在多态:
假如父类和子类拥有相同名字的域,那么会分配两个不同的空间。实际上这种情况基本不存在,因为你通常会将所有的域声明为private,因此不能够直接访问,其次,你可能不会对基类的域与导出类的域赋予相同的名字的。
任何的域访问操作都是由编译器解析,因此不是多态的,如果直接访问域(域是public的情况,本身就很少见),会返回基类的域值。

如果某个方法是静态的,因为静态的方法是类的属性,所以它就不具有多态性。
package source.sunday;
class StaticSuper {
	public static String staticGet() {
		return "Base staticGet";
	}
	public String dynamicGet() {
		return "Base dynamicGet";
	}
}
class StaticBub extends StaticSuper {
	public static String staticGet() {
		return "Derived staticGet";
	}
	public String dynamicGet() {
		return "Derived dynamicGet";
	}
}

public class StaticPolymorphism {
	public static void main(String[] args) {
		StaticSuper ss = new StaticBub();
		System.out.println(ss.staticGet());
		System.out.println(ss.dynamicGet());
	}
}
静态方法是与类,而并非与单个的对象相关联的。
output:


构造器的调用顺序:
1. 调用基类构造器。这个步骤会不断的反复递归下去,首先是构造这种层次结构的根,然后是下一层导出类,等等,直到最底层的导出类。
2. 按声明顺序调用成员的初始化方法。
3. 调用导出类构造器的主体。
注:构造器并不具有多态性,构造器实际上是static方法,只不过该static声明是隐式的。

向下转型
package source.sunday;
class Useful {
	public void f() {}
	public void g() {}
}
class MoreUseful extends Useful {
	public void f() {}
	public void g() {}
	public void u() {}
	public void v()	{}
}

public class RTTI {
	public static void main(String[] args) {
		Useful[] x = {
				new Useful(),
				new MoreUseful()
		};
		x[0].f();
		x[1].g();
		
		((MoreUseful)x[1]).u();
		((MoreUseful)x[0]).u();	//error:会抛出异常!没有此方法。
	}
}
上述错误会抛出异常: java.lang.ClassCastException
Exception in thread "main" java.lang.ClassCastException: com.factory.action.Array cannot be cast to com.factory.action.ArrayExtend




### Java 多态的概念 Java 中的多态是指同一个接口或类可以有多种不同的实现方式。它允许程序在运行时决定调用哪个方法,从而提高代码的灵活性和可扩展性。多态的核心机制依赖于继承、重写以及动态绑定。 #### 动态绑定 当子类覆盖父类的方法时,在运行期间会根据对象的实际类型来决定执行哪一个版本的方法[^1]。这是多态的关键特性之一。 ### 实现多态的方式 Java多态可以通过以下两种主要形式实现: 1. **方法重写(Override)** 2. **接口实现** 以下是具体示例说明如何利用 `instanceof` 运算符避免潜在异常并展示多态的应用场景。 --- ### 示例代码:Java 多态的具体应用 下面是一个完整的例子,展示了如何通过多态性和 `instanceof` 来处理不同类型的对象实例。 ```java // 定义一个基类 Animal class Animal { void makeSound() { System.out.println("Some generic sound"); } } // 子类 Dog 继承自 Animal 并重写了 makeSound 方法 class Dog extends Animal { @Override void makeSound() { System.out.println("Bark"); } // 额外的功能只属于狗 void fetchStick() { System.out.println("Fetching stick..."); } } // 子类 Cat 继承自 Animal 并重写了 makeSound 方法 class Cat extends Animal { @Override void makeSound() { System.out.println("Meow"); } // 额外的功能只属于猫 void climbTree() { System.out.println("Climbing tree..."); } } public class PolymorphismExample { public static void main(String[] args) { // 创建多个动物对象并通过向上转型存储它们 Animal myDog = new Dog(); Animal myCat = new Cat(); // 调用各自的 makeSound 方法 myDog.makeSound(); // 输出 Bark myCat.makeSound(); // 输出 Meow // 如果需要访问特定子类功能,则需使用 instanceof 和强制转换 if (myDog instanceof Dog) { ((Dog) myDog).fetchStick(); // 正确调用了 Dog 类中的特有方法 } if (myCat instanceof Cat) { ((Cat) myCat).climbTree(); // 正确调用了 Cat 类中的特有方法 } Object cValue = 42; // 假设我们有一个未知类型的变量 // 判断其实际类型并打印相应消息 System.out.println("The type of value is " + (cValue instanceof Double ? "Double" : (cValue instanceof Integer ? "Integer" : "Unknown"))); // 输出 Integer [^2] } } ``` 上述代码片段中: - 我们定义了一个通用的 `Animal` 类作为超类。 - 然后创建两个派生类 `Dog` 和 `Cat`,分别实现了自己的行为逻辑。 - 在主函数里演示了即使将这些对象赋给更广泛的父类引用 (`Animal`),仍然能够正确表现出各自的行为特征——这就是所谓的“编译看声明类型, 执行找真实类型”。 另外还加入了关于 `instanceof` 关键字使用的部分,用于确认某个对象的确切类别以便安全地进行向下造型操作而不会引发 ClassCastException 错误。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值