Java初识继承和多态
2017-11-22 20:18
295 查看
以前学C的时候没学好类和对象,导致对继承和多态更是不了解。现在就趁着学Java的机会重新好好学这部分的内容。
我们知道,面向对象程序设计的三个特点是封装、继承和多态。
1、封装:定义类即为对数据的封装。
2、继承:子类从父类继承可访问的数据域和方法,还可以添加一些新的方法和数据域域以满足新的需求。因此继承的好处就是代码复用。
判断是否需要继承:"is-a"关系是继承的一个明显特征。里氏替换原则定义:继承必须确保超类所拥有的性质在子类中仍然成立。即当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-a关系。
因此在通过扩展超类定义子类时仅需指出子类与超类的不同之处。在设计类时,应该将通用的方法放到超类中,而将具有特殊用途的方法放到子类中。
此外,要注意Java中不允许多重继承,一个类只可能来自一个父亲,即单一继承。
3、多态:父类对象的地方都可以使用子类的对象,就意味着父类型的变量可以引用子类型的对象。
动态绑定:程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。因为在程序运行时才确定具体的类(对象的实际类),而调用哪个方法是由实际类型决定的。这样不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,让程序可以选择多个运行状态。
下面是用来进行测试的代码:
1、GeometricObject类的每个构造方法中,都要记得初始化dateCreated。这一点很容易漏掉,特别是两个参的构造函数中会以为没有其他的数据域需要初始化。
2、super(color,filled);这句话一定要是构造方法的第一条语句!否则会引起语法错误。
这里就涉及到super关键字。它有两种用途,调用父类的构造方法和调用父类的方法,我们一般只用前面一种。因为父类的构造方法不被子类继承,只能在子类的构造方法中用关键字super调用。注意:构造方法可以调用重载的构造方法或它的父类的构造方法,但如果它们都没有被显式地调用,编译器会自动将super()作为构造方法的第一条语句。因此又牵扯到了构造方法链:构造一个类的实例时,将会调用沿着继承链的所有父类的构造方法。当构造一个子类对象时,子类构造方法会在完成自己任务之前,首先调用它父类的构造方法。
3、this.setColor(color);这句话要小心,很容易写成this.color=color;,但这是错的。父类中的私有数据域不能被除了本类之外的其他任何类访问。唯一读取和改变它们的方法就是get和set方法。
最后补充一点:
要十分注意对象转换,特别是需要进行显式转换的地方,括号别漏加错加(其他例子可见ArrayList那篇文章中的代码)。
例如:Object o=new Student(); Student b=o; 会发生编译错误->改为Student b=(Student)o;
因为向下转换(父类到子类)必须使用显式转换向编辑器表明意图。
此外,为了要保证转换成功,在尝试转换之前要确保该对象是另一个对象的实例(用运算符instanceof实现):
Object myObject=new Circle();
//...
if(myObject instanceof Circle)
System.out.println(((Circle)myObject).getRadius());
//...
我们知道,面向对象程序设计的三个特点是封装、继承和多态。
1、封装:定义类即为对数据的封装。
2、继承:子类从父类继承可访问的数据域和方法,还可以添加一些新的方法和数据域域以满足新的需求。因此继承的好处就是代码复用。
判断是否需要继承:"is-a"关系是继承的一个明显特征。里氏替换原则定义:继承必须确保超类所拥有的性质在子类中仍然成立。即当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-a关系。
因此在通过扩展超类定义子类时仅需指出子类与超类的不同之处。在设计类时,应该将通用的方法放到超类中,而将具有特殊用途的方法放到子类中。
此外,要注意Java中不允许多重继承,一个类只可能来自一个父亲,即单一继承。
3、多态:父类对象的地方都可以使用子类的对象,就意味着父类型的变量可以引用子类型的对象。
动态绑定:程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。因为在程序运行时才确定具体的类(对象的实际类),而调用哪个方法是由实际类型决定的。这样不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,让程序可以选择多个运行状态。
下面是用来进行测试的代码:
public class Text { public static void main(String[] args) { Triangle t=new Triangle(1,1.5,1); t.setColor("yellow"); t.setFilled(true); System.out.println(t.getArea()); System.out.println(t.getPerimeter()); System.out.println(t.getColor()); System.out.println(t.isFilled()); Circle c=new Circle(1); c.setColor("yellow"); c.setFilled(true); System.out.println(c.toString()); } } class GeometricObject{ private String color; private boolean filled; private java.util.Date dateCreated; GeometricObject(){ dateCreated=new java.util.Date();//!!!attention } GeometricObject(String color,boolean filled){ this.color=color; this.filled=filled; dateCreated=new java.util.Date(); } public String getColor() { return color; } public void setColor(String color) { this.color=color; } public boolean isFilled() { return filled; } public void setFilled(boolean filled) { this.filled=filled; } public java.util.Date getDateCreated(){ return dateCreated; } public String toString() { return "Created on "+dateCreated+"\nColor : "+color+" and filled : "+filled; } } class Triangle extends GeometricObject{ private double side1; private double side2; private double side3; Triangle(){ this(1.0,1.0,1.0); } Triangle(double side1,double side2,double side3){ this.side1=side1; this.side2=side2; this.side3=side3; } public double getSide1() { return side1; } public double getSide2() { return side2; } public double getSide3() { return side3; } public double getArea() { double p=(side1+side2+side3)/2; return Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); } public double getPerimeter() { return side1+side2+side3; } public String toString() { return "Triange : side1 = "+side1+"side2 = "+side2+" side3 = "+side3; } } /*class Circle extends GeometricObject{ private double radius; Circle(){ } Circle(double radius){ this.radius=radius; } Circle(double radius,String color,boolean filled){ //super(color,filled);//attention:must be the first statement this.radius=radius; this.setColor(color);//!!!attention:cannot use ’ this.color=color’ this.setFilled(filled); } public double getRadius() { return radius; } public String toString() { return "Created on "+this.getDateCreated()+"\nColor : "+this.getColor()+" and filled : "+this.isFilled(); } }*/先分析一下代码,其中有几个地方要特别注意(从上至下有标注的地方):
1、GeometricObject类的每个构造方法中,都要记得初始化dateCreated。这一点很容易漏掉,特别是两个参的构造函数中会以为没有其他的数据域需要初始化。
2、super(color,filled);这句话一定要是构造方法的第一条语句!否则会引起语法错误。
这里就涉及到super关键字。它有两种用途,调用父类的构造方法和调用父类的方法,我们一般只用前面一种。因为父类的构造方法不被子类继承,只能在子类的构造方法中用关键字super调用。注意:构造方法可以调用重载的构造方法或它的父类的构造方法,但如果它们都没有被显式地调用,编译器会自动将super()作为构造方法的第一条语句。因此又牵扯到了构造方法链:构造一个类的实例时,将会调用沿着继承链的所有父类的构造方法。当构造一个子类对象时,子类构造方法会在完成自己任务之前,首先调用它父类的构造方法。
3、this.setColor(color);这句话要小心,很容易写成this.color=color;,但这是错的。父类中的私有数据域不能被除了本类之外的其他任何类访问。唯一读取和改变它们的方法就是get和set方法。
最后补充一点:
要十分注意对象转换,特别是需要进行显式转换的地方,括号别漏加错加(其他例子可见ArrayList那篇文章中的代码)。
例如:Object o=new Student(); Student b=o; 会发生编译错误->改为Student b=(Student)o;
因为向下转换(父类到子类)必须使用显式转换向编辑器表明意图。
此外,为了要保证转换成功,在尝试转换之前要确保该对象是另一个对象的实例(用运算符instanceof实现):
Object myObject=new Circle();
//...
if(myObject instanceof Circle)
System.out.println(((Circle)myObject).getRadius());
//...
相关文章推荐
- 初识JAVA(【面向对象】:pub/fri/pro/pri、封装/继承/多态、接口/抽象类、静态方法和抽象方法;泛型、垃圾回收机制、反射和RTTI)
- 七、java之封装、继承、多态
- Java学习笔记_10_继承和多态(补充)
- java语言程序设计 李元朝 第7章 类的继承和多态机制 练习题答案
- 【Java学习笔记之十六】浅谈Java中的继承与多态
- 温习Java笔记(5):构造函数、继承和多态
- Java的继承和多态
- Java学习笔记---继承和多态
- 【JAVA语言程序设计第十版 11.2】+ 多态 + 继承
- Java三大特性——继承,封装和多态
- java基础之继承和多态概念
- 黑马程序员——Java基础--继承、多态、抽象、接口联合使用的案例
- 初识JAVA4(抽象类、接口、多态)
- Java-P:继承和多态【只有提纲】
- java面向对象的三大基本特征之封装,继承,多态
- Java入门笔记-(面向对象:封装,多态,继承)
- java中继承和多态的区别
- 学习Java继承和多态时的一个小demo
- Java面向对象(二)面向对象的特征 --- 封装 、 继承、 多态
- Java的继承、封装与多态