目录
- 1.继承
- 1.1为什么要使用继承?
- 1.2继承的概念
- 1.3对继承的理解
- 1.4子类怎么访问父类的成员变量
- 1.4.1不同名怎么访问?
- 1.4.2同名怎么访问?(关键字:super)
- 1.5子类中访问父类的成员方法
- 1.5.1不同名怎么访问?
- 1.5.2同名怎么访问?(关键字:super)
- 1.6super和this
- 1.7 重谈初始化
- 1.8修饰关键字(private、default、protected、public)
- 1.9继承方式
1.继承
1.1为什么要使用继承?
Java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑。下面我们来举一个例子吧。
//这是一个对狗定义的类
class Dog{public String name;public int age;public String color;public void eat(){System.out.println(this.name +"正在吃饭");}public void bark(){System.out.println(this.name +"正在汪汪汪!");}
}
//这是一个对猫定义的类
class Cat{public String name;public int age;public String color;public void eat(){System.out.println(this.name +"正在吃饭");}public void miaomiao(){System.out.println(this.name +"正在喵喵喵!");}
}
通过上面的两个类我们会发现他们有相同的地方
我们可以把这些抽取出来放到一个公共类里面如下的Animal类。
这样当我们定义一个动物的类(如:Dog、Cat、Bird等)就可以继承Amimal类,使代码更加简洁。如下所示:
class Animal{public String name;public int age;public String color;public void eat(){System.out.println(this.name +"正在吃饭");}
}
class Dog extends Animal{public void bark(){System.out.println(this.name +"正在汪汪汪!");}
}
class Cat extends Animal{public void miaomiao(){System.out.println(this.name +"正在喵喵喵!");}
}
1.2继承的概念
继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
1.3对继承的理解
如上所示,我们可以认为是一个is-a
的关系,如狗是一种动物
注意:
1.子类会将父类中的成员变量或者成员方法继承到子类中了
2.子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
1.4子类怎么访问父类的成员变量
1.4.1不同名怎么访问?
1.4.2同名怎么访问?(关键字:super)
当子类和父类有同名变量时我们使用super.可以访问父类中的变量。this.优先访问子类中变量,子类没有再访问父类变量。
1.5子类中访问父类的成员方法
1.5.1不同名怎么访问?
同访问成员变量一样,成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。
1.5.2同名怎么访问?(关键字:super)
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错。这时,我们要访问父类中的方法时可以使用super.。
注意:
- 在静态方法中是不能使用super和this的。
- 当子类继承了父类后在实例化子类对象的时候要先帮助父类进行构造(初始化父类的成员)。初始化父类成员只有一种方法:调用构造方法。如下所示:
public Dog(){super(里面加父类参数初始化的值);
}
- 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
- 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
- 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
- super(…)只能在子类构造方法中出现一次,并且不能和this同时出现
1.6super和this
相同点
1.都是Java中的关键字
2.只能在类的非静态方法中使用,用来访问非静态成员方法和字段
3.在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在。
不同点
1.this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
2.在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
3.在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现
4.构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有
1.7 重谈初始化
class Animal {public String name;public int age;public String color;static {System.out.println("Animal::static{}");}{System.out.println("Animal::{}");}public Animal(String name, int age, String color) {this.name = name;this.age = age;this.color = color;System.out.println("Animal(String,int,String)");}public void eat() {System.out.println(this.name +" 正在吃饭!");}
}
class Dog extends Animal{static {System.out.println("Dog::static{}");}{System.out.println("Dog::{}");}public Dog() {super("haha",10,"黄色");System.out.println("Dog()");}public void bark() {System.out.println(this.name +" 正在汪汪汪!");}
}
public class Test2 {public static void main(String[] args) {Dog dog1 = new Dog();//1System.out.println("==============");Dog dog2 = new Dog();//2}
}
如上方代码所示,在main方法中我们初始化了两个Dog。在父类Animal中有一个静态打印代码块,有一个普通的代码块,在子类Dog中同样,那当我们初始化的时候会出现怎样的打印结果呢?
如上图所示,中间为打印结果,通过分析执行结果,得出以下结论:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
1.8修饰关键字(private、default、protected、public)
如上表所示:
首先有两个极端的关键字:private:只有当前类可以使用、public:任何情况下都可使用。
default:同一个包中当前类和不同类通用。
protected:和default不同的是可以不同包的子类中访问,但是要注意我们只能通过关键字super来进行访问,如下图所示:
上面的不同包的访问建立在一个前提:继承的类被public修饰。
1.9继承方式
Java中的继承分为以下几种
1.单继承
2.多层继承
3.不同类继承一个类