Java之继承
目录
1.继承
2.父类成员访问
2.1子类中访问父类的成员变量
2.1.1子类和父类不存在同名成员变量
2.1.2子类和父类同名
2.2子类中访问父类的成员方法
3.super关键字
4.子类构造方法
5.super和this
6.再谈初始化
7.protected 关键字(不同包中的子类)
8.继承方式
9.组合与继承
1.继承
class Animal{
public String name;
public int age;
public String color;
public void eat(){
System.out.println(name + "正在吃饭!");
}
}
class Dog extends Animal{
// 子类 继承 父类
// 派生类 基类
// 超类
}
class Cat extends Animal{
}
- 前提是子类和父类之间是一种 is-a
E.G. Dog is a/an animal
E.G. class Robot extends Animal 不建议设计为继承!!!
- 面对两个类中共有的属性或方法,采用继承的方法 (方法名用小驼峰)
- 父类一定是子类的共性,子类继承父类之后,会继承父类成员方法和成员变量,达到了代码的复用效果
- 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没必要继承了
2.父类成员访问
2.1子类中访问父类的成员变量
2.1.1子类和父类不存在同名成员变量
import jdk.internal.org.objectweb.asm.tree.MultiANewArrayInsnNode;
class Base{
public int a;
public int b;
}
class Derived extends Base{
public int c;
//访问父类成员变量
public void method(){
a = 10;
b = 20;
c = 30;
}
}
public class Test{
public static void main(String[] args) {
Derived derived = new Derived();
}
}
2.1.2子类和父类同名
class Base{
public int a;
public int b;
}
class Derived extends Base{
public int c;
public int a;
public void method{
a = 10;//这里的a是子类的a
b = 20;
c = 30;
}
}
当子类和父类是同名的成员变量的时候
1.在子类当中访问这个同名的成员变量
访问的是子类自己的!就近原则,优先访问子类
2.如果一定要访问父类的a,那么此时就要用到另一个关键字super
class Base{
public int a = 1;
public int b = 2;
public int d = 99;
}
class Derived extends Base {
public int c = 3;
public int a = 4;
public void method() {
System.out.println(super.a);//父类
System.out.println(this.a);//子类
System.out.println(this.b);
System.out.println(this.c);
System.out.println(this.d);
}
}
public class Da{
public static void main(String[] args) {
Derived derived = new Derived();
}
}
1.this访问的时候 不仅可以访问父类 也可以访问子类的
2.当使用this访问父类和子类同名的成员变量的时候,子类优先访问
3.super只能访问从父类继承过来的成员变量
4.super只是一个关键字!!有些书上会说 他代表父类对象的引用 其实是错的!!!
严格点说:就是一个关键字,提高代码的可读性,让别人看到这样访问就知道是访问父类的关键字!!!
2.2子类中访问父类的成员方法
成员方法名相同
import jdk.internal.org.objectweb.asm.tree.MultiANewArrayInsnNode;
class Base{
public void func1(){
System.out.println("func1()");
}
}
class Derived extends Base{
public void func2(){
System.out.println("func2()");
}
public void func1(int a){
System.out.println("func1()");
}
public void func1(){
System.out.println("func1()");
}
public void testFunc(){
func2();
func1(10);//子类的 重载!!
func1();//子类的
super.func1();//父类的
}
}
public class Test{
public static void main(String[] args) {
Derived derived = new Derived();
}
}
总之:先在子类找,子类没有去父类找,父类也没有,编译报错!!!
super.data 访问父类的成员变量
super.func() 访问父类的成员方法
super() 调用父类的构造方法--》稍后讲解
3.super关键字
该关键字主要作用:在子类方法中访问父类
super在当前类当中使用,那么当前类一定是子类!!!
- 只能在非静态方法中使用
- 在子类方法中,访问父类的成员变量和方法
什么是继承?对共性进行抽取
为什么继承?达到代码的复用
子类继承了父类的什么???
4.子类构造方法
当子类继承父类之后,一定要先帮助父类进行构造,然后再构造子类自己!!!
只能在子类当中,调用父类的构造方法
1.若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用
2.如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造法方法中选择合适的父类构造方法调用
3.在子类构造方法中,super()调用父类构造时,必须是子类构造函数的第一条语句
4.super()只能在子类构造方法中出现一次,并且不能和this同时出现
class Animal {
public String name;
public int age;
public String color;
/*public Animal(){
}*/
public Animal(String name) {
this.name = name;
}
public void eat(){
System.out.println(name+"正在吃饭!");
}
}
class Dog extends Animal{
/*public Dog(){
super();
}*/
public Dog(String name){
super(name);//来调用你想调用的构造方法 此时就相当于先帮助父类进行了初始化操作
/*this();*/
//在调用构造方法的时候,不能同时存在!
//因为他们两个都只能在第一行!!!
}//执行完 这个括号之后 子类构造完了
public void wangWang(){
System.out.println(name + "正在汪汪汪!");
super.name = "12";
this.eat();//此时this super不冲突
}
}
5.super和this
1.都是Java中的关键字
2.只能在类的非静态方法中使用,用来访问非静态成员方法和字段
3.在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
【不同点】
1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
2.在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
3.在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现
4.构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有
6.再谈初始化
class Animal {
public String name;
public int age;
public String color;
static{
System.out.println("Animal的静态代码块!");
}
{
System.out.println("Animal的实例代码块!");
}
public Animal(String name) {
this.name = name;
System.out.println("Animal(string)");
}
public void eat(){
System.out.println(name+"正在吃饭!");
}
}
class Dog extends Animal{
static{
System.out.println("Dog的静态代码块!");
}
{
System.out.println("Dog的实例代码块!");
}
public Dog(String name){
super(name);
System.out.println("Dog的构造方法");
}
public void wangWang(){
System.out.println(name + "正在汪汪汪!");
}
}
public class Test{
public static void main(String[] args) {
Dog dog1 = new Dog("小狗1");
/*System.out.println("========");
Dog dog2 = new Dog("小狗2");*/
}
}
一个对象的运行结果:
两个对象的运行结果:
通过分析执行结果,得出以下结论:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
7.protected 关键字(不同包中的子类)
在类和对象章节中,为了实现封装特性,Java引入了访问限定符,主要限定:类或者类中的成员能否在类外或者其他包中被访问。
main方法是static修饰的,super不能用在static修饰的方法当中
什么时候下用哪一种呢?
我们希望类要尽量做到"封装",即隐藏内部实现细节,只暴露出 必要 的信息给类的调用者
因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限.例如如果一个方法能用 private,就尽量不要用public
另外,还有一种 简单粗暴 的做法:将所有的字段设为 private, 将所有的方法设为 public。不过这种方式属于是对访问权限的滥用,还是更希望同学们能写代码的时候认真思考,该类提供的字段方法到底给"谁"使用(是类内部自己用,还是类的调用者使用,还是子类使用)
8.继承方式
Java不支持多继承
public final class Da{
protected int a = 99;
}
//如果一个类不想被继承的时候,那么就使用关键字final进行修饰
//此时这个类将不能被继承 密封类
//常量 常量是不能进行修改的
final int a = 10;
a = 20;//报错
//不能修改array1这个变量当中存储的值,简单说:不能让array1指向新的对象!!
final int[] array1 = {1,2,3,4,5};
array1 = new int[10];//报错
还有我们平时用的是String字符串类,就是用final修饰的,不能被继承
9.组合与继承
在一个类中,用别的类作为我的成员