对继承与多态、成员变量的隐藏和方法重写、super关键字、final关键字、对象的上转型对象、抽象类的学习理解(java)
对Java子类与继承的简单理解
继承
是一种由已有的类创建新类的机制。利用继承,我们可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加它自己的新的状态和行为。由继承而得到的类称为子类,被继承的类称为父类(超类)。
注:Java不支持多重继承(子类只能有一个父类)。
声明子类
使用关键字extends来定义一个类的子类,格式如下:
class 子类名 extends 父类名 {
…
}
例如:
class Student extends People {
…
}
说明:把Student类定义为People类的子类、People类是Student类的父类
子类的继承性
类可以有两种重要的成员:成员变量和方法。子类的成员中有一部分是子类自己声明定义的,另一部分是从它的父类继承的。
所谓子类继承父类的成员变量就是把继承来的变量作为自己的一个成员变量,就好象它们是在子类中直接声明一样,可以被子类中自己定义的任何实例方法操作。
所谓子类继承父类的方法就是把继承来的方法作为子类中的一个方法,就好象它们是在子类中直接定义了一样,可以被子类中自己定义的任何实例方法调用。
例题:子类的继承
class Father
{ float weight,height;
String head;
void speak(String s)
{ System.out.println(s);
}
}
class Son extends Father
{ String hand,foot;
}
Son s=new Son();
子类和父类在同一包中的继承性
如果子类和父类在同一个包中,那么,子类自然地继承了其父类中不是private的成员变量作为自己的成员变量,并且也自然地继承了父类中不是private的方法作为自己的方法,继承的成员变量或方法的访问权限保持不变。
子类和父类不在同一包中的继承性
如果子类和父类不在同一个包中,那么,子类继承了父类的protected、public成员变量做为子类的成员变量,并且继承了父类的protected、public方法为子类的方法,继承的成员或方法的访问权限保持不变。
子类对象的生成
子类创建对象时,子类的构造方法总是先调用父类的某个构造方法,完成父类部分的创建;然后再调用子类自己的构造方法,完成子类部分的创建。如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类的不带参数的构造方法 。
子类创建对象时,子类的构造方法总是先调用父类的某个构造方法,完成父类部分的创建;然后再调用子类自己的构造方法,完成子类部分的创建。如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类的不带参数的构造方法 。
子类可以通过继承的方法来操作子类未继承的变量和方法 .
结论:
1)创建子类对象时,子类总是按层次结构从上到下的顺序调用所有超类的构造函数。如果继承和组合联用,要先构造基类的构造函数,然后调用组合对象的构造函数(组合按照声明的顺序调用)。
2)如果父类没有不带参数的构造方法,则在子类的构造方法中必须明确的告诉调用父类的某个带参数的构造方法,通过super关键字,这条语句还必须出现在构造方法的第一句。
成员变量的隐藏和方法重写
1)对于子类可以从父类继承的成员变量,只要子类中声明的成员变量和父类中的成员变量同名时,子类就隐藏了继承的成员变量
在子类中要操作这个与父类同名的成员变量时,子类操作的是子类重新声明的这个成员变量。而不是被隐藏掉的。
2)
1.重写的语法规则
如果子类继承了父类的实例方法,那么子类就有权利重写这个方法。
方法重写是指:子类中定义一个方法,这个方法的类型和父类的方法的类型一致或是父类方法的类型的子类型,且这个方法的名字、参数个数、参数的类型和父类的方法完全相同.
2.重写的目的
子类通过方法的重写可以隐藏继承的方法,子类通过方法的重写可以把父类的状态和行为改变为自身的状态和行为。
3. 重写后方法的调用
子类创建的一个对象,如果子类重写了父类的方法,则运行时系统调用的是子类重写的方法;
子类创建的一个对象,如果子类未重写父类的方法,则运行时系统调用的是子类继承的方法;
4.重写的注意事项
重写父类的方法时,不允许降低方法的访问权限,但可以提高访问权限(访问限制修饰符按访问权限从高到低的排列顺序是:public、protected、友好的、private。)
super关键字
1 用super操作被隐藏的成员变量和方法
子类可以隐藏从父类继承的成员变量和方法,如果在子类中想使用被子类隐藏的成员变量或方法就可以使用关键字super。比如super.x、super.play()就是访问和调用被子类隐藏的成员变量x和方法play().
2 使用super调用父类的构造方法
子类不继承父类的构造方法,因此,子类如果想使用父类的构造方法,必须在子类的构造方法中使用,并且必须使用关键字super来表示,而且super必须是子类构造方法中的头一条语句。
final关键字
final关键字可以修饰类、成员变量和方法中的局部变量。
可以使用final将类声明为final类。final类不能被继承,即不能有子类。
如: final class A {
… …
}
如果用final修饰父类中的一个方法,那么这个方法不允许子类重写。
如果成员变量或局部变量被修饰为final的,就是常量。
对象的上转型对象
假设,A类是B类的父类,当用子类创建一个对象,并把这个对象的引用放到父类的对象中时,称对象a是对象b的上转型对象。比如:
A a;
a=new B();
或
A a;
B b=new B();
a=b;
上转型对象的使用
1.上转型对象不能操作子类新增的成员变量;不能调用子类新增的方法。
2.上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法。
3. 如果子类重写了父类的某个实例方法后,当用上转型对象调用这个实例方法时一定是调用了子类重写的实例方法。
多态
多态性就是指父类的某个方法被其子类重写时,可以各自产生自己的功能行为。
abstract类和abstract()方法
用关键字abstract修饰的类称为abstract类(抽象类)。
例如:abstract class A {
… …
}
用关键字abstract修饰的方法称为abstract方法(抽象方法)
例如:abstract int min(int x,int y);
abstract类有如下特点
和普通的类相比,abstract类里可以有abstract方法。也可以没有。对于abstract方法,只允许声明,不允许实现,而且不允许使用final修饰abstract方法。
对于abstract类,不能使用new运算符创建该类的对象,只能产生其子类,由子类创建对象。
如果一个类是abstract类的子类,它必须具体实现父类的所有的abstract方法。
面向抽象编程
在设计一个程序时,可以先声明一个abstract类,通过在类中声明若干个abstract方法,表明这些方法在整个系统设计中的重要性,方法体的内容细节由它的非abstract子类去完成。
然后利用多态实现编程。使用多态进行程序设计的核心技术是使用方法重写和上转型对象,即将abstract类声明对象作为其子类的上转型对象,那么这个上转型对象就可以调用子类重写的方法。
所谓面向抽象编程,是指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。
实例
下面举个例子描述继承、重写、抽象类的简单使用。
设计一个动物声音“模拟器”,希望模拟器可以模拟许多动物的叫声,要求如下:
- 编写抽象类Animal
Animal抽象类有两个抽象方法cry()和getAnimalName(),即要求各种具体的动物给出自己的叫声和种类名称。 - 编写模拟器类Simulator
该类有一个playSound(Animal animal)方法,该方法的参数是Animal类型。即animal可以调用Animal的子类重写的cry()方法播放具体动物的声音,调用子类重写的getAnimalName()方法显示动物种类的名称。 - 编写Animal类的子类:Dog和Cat类
- 编写主类Application(用户程序)
在主类Application的main方法中至少包含如下代码;
Simulatoer simulator =new Simulator();
simulator.playSound(new Dog());
simulator.playSound(new Cat());
下表为Simulator、Animal、Dog、Cat的UML图。
//Animal.java
public abstract class Animal{ //定义抽象类
public abstract void cry(); //声明抽象方法
public abstract String getAnimalName();
}
//Simulator.java
public class Simulator{ //编写模拟器类
public void playSound(Animal animal){ //实现调用对象参数方法,即animal参数可以调用Animal类子类的方法
System.out.print("现在播放"+animal.getAnimalName()+"类的声音:");
animal.cry();
}
}
//Dog.java
public class Dog extends Animal{ //编写Dog类继承
public void cry(){ //实现父类方法的内容
System.out.println("汪汪....汪");
}
public String getAnimalName(){
return "狗";
}
}
//Cat.java
public class Cat extends Animal{ //编写Cat类继承
public void cry(){ //实现父类方法的内容
System.out.println("喵喵.....喵喵");
}
public String getAnimalName(){
return "猫";
}
}
//Application.java
public class Application{ //编写主类
public static void main(String args[]){
Simulator simulator=new Simulator(); //创建模拟器对象
simulator.playSound(new Dog()); //调用模拟器方法参数为Animal类型(对象的上转型对象)
simulator.playSound(new Cat());
}
}