文章目录
一、子类与父类:
1、继承的概念:
通过必要的说明能够实现某个类无需重新定义就拥有另一个类的某些属性和方法,把这种关系称为继承,先定义的类成为父类,后定义的类称为子类,并且允许多层的继承关系。
子类创建对象也会默认调用父类的无参构造函数
JAVA中实现继承的语法:
class 子类名字 extends 父类名字{
}
示例:
class Person {
//Person类称 父类,又称超类,基类
protected String name;
protected int age;
public Person(){
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
public void setAge(int age){
this.age = age;
}
public void display(){
System.out.println("姓名:" + name + " 的年龄是: " + age);
}
}
class Student extends Person{
//Student类是子类,又称派生类
private String stuNo;
public Student(){
}
public Student(String stuNo){
name = "张三";
age = 18;
this.stuNo = stuNo;
}
public void displayNo(){
System.out.println("学号是:" + stuNo);
}
}
说明:★★★
1)、Java只支持单一继承,即extends后面只能有一个父类名字。
2)、如果要实现多重继承,只有通过接口实现。
3)、所有的类都派生自Object类。即除了类Object外,凡是没有指明扩展关系的类,都认为是省略了“extends Object”,都派生自类Object。
4)、派生具有传递性。如果类A派生了类B,类B又派生了类C,则C不仅继承了B,也继承了A。
2、继承的作用: 提供软件复用功能。就是让子类拥有父类中相关访问权限的成员变量和成员方法。这种做法能减小代码和数据的冗余度,大大增加程序的重用性。
3、继承关系的UML图:
类与类之间的继承关系,又称为泛化关系。泛化关系UML图是采用直线空心三角形连接两个类,Person类和Student类之间的泛化关系图如下:
二、继承中的成员变量隐藏和方法重写
1、成员变量的隐藏:
对于子类可以从父类继承的成员变量,只要子类中声明的成员变量和父类中的成员变量同名时,子类就隐藏了继承父类的成员变量,子类自己声明定义的方法操作,与父类同名的成员变量,则是子类中重新声明定义的这个成员变量。
注意:子类继承父类其实就是copy了一份,当子类重写隐藏父类成员时,可以用super来调用那些被隐藏的
阅读下面的程序并理解:
Goods.java
public class Goods {
public double weight;
public void oldSetWeight(double w) {
weight=w;
System.out.println("double型的weight="+weight);
}
public double oldGetPrice() {
double price = weight*10;
return price;
}
}
CheapGoods.java
public class CheapGoods extends Goods {
public int weight;
public void newSetWeight(int w) {
weight=w;
System.out.println("int型的weight="+weight);
}
public double newGetPrice() {
double price = weight*10;
return price;
}
}
//UseCheapGoods.java
public class UseCheapGoods{
public static void main(String args[]) {
CheapGoods cheapGoods=new CheapGoods();
cheapGoods.weight=198.98; //是非法的,因为子类对象的weight已经是int型
cheapGoods.newSetWeight(198);
System.out.println("对象cheapGoods的weight的值是:"+cheapGoods.weight);
System.out.println("cheapGoods用子类新增的优惠方法计算价格:"+
cheapGoods.newGetPrice());
cheapGoods.oldSetWeight(198.987); //子类对象调用继承的方法操作隐藏的double型变量weight
System.out.println("cheapGoods使用继承的方法(无优惠)计算价格:"+ cheapGoods.oldGetPrice());
}
}
2、子类对继承父类方法的重写:
子类通过重写可以隐藏已继承的实例方法。
1、重写的语法规则
如果子类可以继承父类的某个实例方法,那么子类就可以对该方法进行重写。
方法重写是指:子类中定义一个方法,这个方法的返回值类型、方法名、参数列表与父类的方法完全相同。
2、重写的目的:
子类通过方法重写可以隐藏继承下来的方法,子类通过方法重写可以把父类的状态和行为改变为自身的状态和行为。
阅读并理解 下面的程序:
//Goods.java
public class Goods {
public double weight;
public void setWeight(double w) {
weight=w;
System.out.println("double型的weight="+weight);
}
public double getPrice() {
double price = weight*10;
return price;
}
}
//CheapGoods.java
public class CheapGoods extends Goods {
public int weight;
public void setWeight(int w) {
//由于参数类型与父类不同,故不是重写
weight=w;
System.out.println("int型的weight="+weight);
}
public double getPrice() {
//重写了父类中的getPrice()方法
double price = weight*5;
System.out.println("我重写了父类的getPrice方法");
return price;
}
}
//UseCheapGoods.java
public class UseCheapGoods{
public static void main(String args[]) {
CheapGoods cheapGoods=new CheapGoods();
cheapGoods.setWeight(198);
System.out.println("对象cheapGoods的weight的值是:"+cheapGoods.weight);
System.out.println("cheapGoods用子类新增的优惠方法计算价格:"+ cheapGoods.getPrice());
cheapGoods.setWeight(198.987);
System.out.println("cheapGoods使用继承的方法(无优惠)计算价格:"+ cheapGoods.getPrice());
}
}
★★★
特别注意:当子类重写了父类的方法时,要注意以下两点:
1、子类的方法不能比父类方法抛出更多的异常。
2、子类的方法不能缩小父类方法的访问权限。
3、重载
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则:
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;(不必要相同的意思)
- 被重载的方法可以改变访问修饰符;(不必要相同)
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
三、super关键字
super的作用:用来连接(使用)当前子类对象中的父类的方法或成员变量。
★1、调用父类的构造方法。super必须在第一行。
调用方法:super([参数]);
class Base{
Base(){
System.out.println("Base");
}
}
public class Test1 extends Base{
Test1(){
super();//这才是对的;如果不加他也会默认调用父类无参构造器
System.out.println("Checket");
}
public static void main(String[] arg){
Test1 c = new Test1();
}
}
2、使用super访问被子类成员隐藏的父类成员或者方法。
调用方法:
super.父类的成员变量;
super.父类的方法名();
理解下面的程序:
class Animal{
//定义一个动物类
int age=3;//如果我把父类的成员变量 权限改为 private 则 子类不可以访问
int weight=5;
Animal(int age,int weight){
//构造方法
this.age = age;
this.weight = weight;
}
public void meow(){
//叫声
System.out.println("Meow......");
}
}
class Cat extends Animal{
int age; //定义年龄
int high; //定义高度
Cat(int a,int w,int h){
super(a,w); //调用父类构造方法
high = h;
}
public void meow(){
System.out.println("喵喵......");
}
public void display(){
System.out.println("父类的age:"+super.age);
System.out.println("父类的weight:"+super.weight);
System.out.println("子类的age:" + age);
super.meow(); //父类中的meow()方法
meow(); //子类中的meow()方法
}
public static void main(String[] arg){
Cat cat = new Cat(3,4,2);
cat.display();
}
}
结果:
★★★
特别注意:子类一定要调用父类中的构 式有两种:
1、当子类的构造方法中没有super()调用父类构造方法时,则子类构造方法默认调用父类的缺省构造方法。
2、当子类的构造方法中有super()调用父类构造方法时,则子类调用父类中参数匹配的父类构造方法。
四、final关键字
final 指的是“不可变的”,"最终的"意思。
final关键字可以用来修饰类、成员方法、成员变量 和方法中的局部变量。
final关键字有四种用法:
1、修饰类:表示该类不能被继承
示例:
JDK系统中的String类定义成final的,String类是不能被继承的:
public final class String extends Object implements Serializable, Comparable, harSequence
fianl class People {
private String name;
public People(String str){
name = str;
}
}
class Student extends People{
} //错误
2、修饰方法:它表示该方法不能被覆盖。
这种使用方式主要是从设计的角度考虑,即明确告诉其他可能会继承该类的程序员,不希望他们去覆盖这个方法。
class