面向对象程序设计的三大支柱是封装、继承和多态。
继承关系使一个子类能继承父类的特征,并且附加一些新特性。子类是它的父类的特殊化,每个子类的实例都是其父类的实例,但是反过来不成立。因此总可以将子类的实例传递给需要父类型的参数。使用父类对象的地方都可以使用子类的对象,这就是通常所说的多态(polymorphism)。简单来说,多态意味着父类型的变量可以引用子类型的对象。
1.2Java多态的实例实例:
1. public class PolymorphismDemo {
2. /** Main method */
3. public static void main(String[] args) {
4. displayObject(new Circle(1, "red", false));
5. displayObject(new Rectangle(1, 1, "black", true));
6.
7. }
8.
9. /** Display geometric object properties */
10. public static void displayObject(GeometricObject object) {
11. System.out.println("Created on " + object.getDateCreated() +
12. ". Color is " + object.getColor());
13. }
14. }
输出:
1. Created on Thu Apr 21 10:46:30 CST 2022. Color is red
2. Created on Thu Apr 21 10:46:30 CST 2022. Color is black
Circle和Rectangle都是GeometricObject的子类,方法displayObject(第10行)具有GeometricObject类型的参数。可以传递任何一个GeometricObject的实例来调用,Circle和Rectangle的实例都是GeometricObject的实例,所以第4行和第5行对displayObject的调用是正确的。
2.动态绑定 2.1动态绑定与多态多态是动态绑定的的使用,动态绑定是多态的实现原理。
2.2什么是动态绑定示例代码:
1. Object o = new GeometricObject();
2. System.out.println(o.toString());
一个变量必须被声明为某种类型,变量的这个类型称为它的声明类型(declared type)。例如这里o的声明类型就是Object。
一个引用类型变量可以是一个null值或者是对一个声明类型实例的引用。实例可以是使用声明类型或它的子类型的构造方法创建。变量的实际类型(actual type)是被引用的对象的实际类。例如这里,o的实际类型是GeometricObject,因为o引用使用new GeometricObject()创建的对象。o调用哪个toString()由o的实际类型决定,这就称为动态绑定(dynamic bingding)。
2.3类型转换1.向上转型不要强制转换
2.父类引用指向的或者调用的方法是子类的方法,这个叫动态绑定
3.向上转型后父类引用不能调用子类自己的方法
例子:
1. public class Human {
2. public void sleep() {
3. System.out.println("Human sleep..");
4. }
5. public static void main(String[] args) {
6. // (1)向上转型
7. Male m1 = new Male();
8. Human h1 = m1;
9. h1.sleep();
10. //h1.speak(); // 此时需要向下转型,否则不能调用speak方法。
11.
12. // // (2)向下转型
13. // Male m2 = new Male();
14. // Human h2 = m2;
15. // m2 = (Male) h2;
16. // m2.speak();
17.
18. // // (3)向下转型:失败
19. // Human h3 = new Human();
20. // Male m3 = (Male)h3;
21. // m3.speak(); //此时会出现运行时错误,所以可以用instanceOF判断
22. //
23. // // (4)向下转型:类型防护
24. // Human h4 = new Human();
25. // if (h4 instanceof Male){ // 因为h4不是Male的实例,所以不执行if内部代码
26. // Male m4 = (Male)h4;
27. // m4.speak();
28. // }
29. }
30. }
31. class Male extends Human {
32. @Override
33. public void sleep() {
34. System.out.println("Male sleep..");
35. }
36.
37. public void speak() {
38. System.out.println("I am Male");
39. }
40. }
2.4动态绑定的工作机制
假设对象o是类C1, C2, …, Cn-1, Cn的实例,其中C1是C2的子类,C2是C3的子类,…,Cn-1是Cn的子类。即Cn是最通用的类,C1是最特殊的类。如果对象o调用一个方法p,那么JVM会依次在类C1, C2, …, Cn-1, Cn中查找方法p的实现,直到找到为止。
例子:
1. public class DynamicBindingDemo {
2. public static void main(String[] args) {
3. m(new GraduateStudent());
4. m(new Student());
5. m(new Person());
6. m(new Object());
7. }
8.
9. public static void m(Object x) {
10. System.out.println(x.toString());
11. }
12.
13. }
14.
15. class GraduateStudent extends Student {
16. }
17.
18. class Student extends Person {
19. @Override
20. public String toString() {
21. return "Stuendt";
22. }
23. }
24.
25. class Person extends Object {
26. @Override
27. public String toString() {
28. return "Person";
29. }
30. }
输出:
1. Student
2. Student
3. Person
4. java.long.Object@130c19b
3.多态应用
为了进行通用程序设计,好的做法是把变量定义为父类型,这样,它可以接受任何子类型
例子:
1. public class CastingDemo {
2. /** Main method */
3. public static void main(String[] args) {
4. // Create and initialize two objects
5. Object object1 = new Circle(1);
6. Object object2 = new Rectangle(1, 1);
7.
8. // Display circle and rectangle
9. displayObject(object1);
10. displayObject(object2);
11. }
12.
13. /** A method for dispalying an object */
14. public static void displayObject(Object object) {
15. if (object instanceof Circle) {
16. System.out.println("The cielce area is " +
17. ((Circle)object).getArea());
18. System.out.println("The circle diameter is " +
19. ((Circle)object).getDiameter());
20. }
21. else if (object instanceof Rectangle) {
22. System.out.println("The rectangle area is " +
23. ((Rectangle)object).getArea());
24. }
25. }
26.
27. }
输出:
1. The cielce area is 3.141592653589793
2. The circle diameter is 2.0
3. The rectangle area is 1.0
4.抽象类
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。在Java语言中使用 abstract 来定义抽象类和抽象方法。
抽象方法是出现在基类中的一种方法,但要求在派生类中被重写。一个抽象方法只有方法头,没有方法主体。例如:
- public abstract void getArea();
若类含有抽象方法,则类必须以abstract关键字声明为抽象类。
- public abstract class 类名
注意:
- 抽象类可以含零至多个普通方法,也可以含零至多个抽象方法。
- 不论抽象类是否含抽象方法,其都不允许实例化,即不能创建抽象类的对象,因为其描述的是抽象概念。它只能作为其他类的基类。
- 不论抽象类是否含抽象方法,其都不允许实例化,即不能创建抽象类的对象,因为其描述的是抽象概念。它只能作为其他类的基类。
例子:
1. public abstract class Employee
2. {
3. private String name;
4. private String address;
5. private int number;
6.
7. public abstract double computePay();
8.
9. //其余代码
10. }
1. /* 文件名 : Salary.java */
2. public class Salary extends Employee
3. {
4. private double salary; // Annual salary
5.
6. public double computePay()
7. {
8. System.out.println("Computing salary pay for " + getName());
9. return salary/52;
10. }
11.
12. //其余代码
13. }
Employee类是抽象类含有抽象方法computePay不允许实例化。Salary类是Employee类的子类并且重写了computePay方法,Salary类不是抽象类,可以实例化。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)