继承+覆写+final关键字

196 阅读4分钟

一:继承

要点:继承的主要作用和实现,继承的相关限制和使用规则
继承主要是为了解决代码的重用

继承的实现 

语法:  class  子类   extends   父类  {  }
注意:   子类又叫派生类,相当于对已有类的一个扩充。父类又叫基类或超类(super class)

class Person{//人类   ---父类
	private String name;
	private int age;
	//设置私有属性值的函数
	public void setName(String name) {
		this.name=name;
	}
	public void setAge(int age) {
		this.age=age;
	}
	//得到私有属性值的函数
	public String getName() {
		return this.name;
	}
	public int getAge() {
		return this.age;
	}
}
class Student extends Person{//继承类
	/*没有任何方法*/
}

public class transfer {
     public static void main(String[] args) {
	        Student stu=new Student();
	        stu.setName("张三");
	        stu.setAge(50);
	        System.out.println(stu.getName()+" "+stu.getAge());
    }
}

运行结果:张三 50

子类不扩充任何操作,即没有定义新方法,但也可以直接在主程序中调用其父类的所有方法。

子类添加新方法

class Person{//人类   ---父类
	private String name;
	private int age;
	public void setName(String name) {
		this.name=name;
	}
	public void setAge(int age) {
		this.age=age;
	}
	public String getName() {
		return this.name;
	}
	public int getAge() {
		return this.age;
	}
}
class Student extends Person{//继承类
	/*新增school属性并且添加获得学校和设置学校的方法*/
	private String school;
	public void setSchool(String school) {
		this.school=school;
	}
	public String getSchool() {
		return this.school;
	}
}

public class transfer {
     public static void main(String[] args) {
	        Student stu=new Student();
	        stu.setName("张三");
	        stu.setAge(50);
	        stu.setSchool("北京大学");//新增学校赋值
	        System.out.println(stu.getName()+" "+stu.getAge()+" "+stu.getSchool());
    }
}

程序运行结果:张三 50 北京大学

表明子类可以直接调用父类的方法也可以定义自己的新方法。

继承的本质:在代码重用的基础上,扩充方法或属性。

继承的限制 

限制一:区别于C++,java不允许多重继承,也就是说:一个子类不可以继承多个父类。

但是:java可以多层继承,如:A继承B,B继承C。。。

 注意:一般不用超过三层,否则会造成代码混乱。

限制二:子类会继承父类的全部操作,但是对于所有的私有操作是隐式继承,所有的非私有操作会显示继承。 

class A{
	private String msg="hello";
	public void setMsg(String msg) {
		this.msg=msg;}
	public String getMsg() {
		return msg;
	}
}
class B extends A{
	
}
public class transfer {
     public static void main(String[] args) {
	      B b=new B();
	      b.setMsg("world");
	      System.out.println(b.getMsg());
    }
}

程序运行结果:world;
实际上--msg是A的私有属性,但是B继承A后,实例化B类对象b后可以输出msg的值,表明继承可以继承私有属性。但是父类的私有属性,子类不可以直接定义函数访问到。

属性改为public才可以,也就是派生类不可以自己定义访问父类私有属性的函数。 

 限制三:

有关继承的构造函数

 发现实例化子类对象时,会先调用父类构造函数,在调用子类构造函数。这也符合我们继承的逻辑,现有父亲,再有儿子。但是前提是:无参构造函数。这里实际上省略了:super();

父类构造函数有参数时:

class A{
	private String title;
	public A(String title) {
		System.out.println("A类(父类)的构造函数");
	}
}
class B extends A{
	public B(String title) {//参数必须和父类一致或多
		super(title);//有参,此代码必须加,且放在首行
		System.out.println("B类(子类)的构造函数");
	}
}
public class transfer {
     public static void main(String[] args) {
	     new B("hello");
    }
}


/*运行结果:
A类(父类)的构造函数
B类(子类)的构造函数
*/

总结:子类构造函数必须在父类构造函数基础上进行,super()和this()不可以同时出现。

class Person{//人类   ---父类
	private String name;
	private int age;//父类构造函数
	public Person(String name,int age) {
		this.name=name;
		this.age=age;
	}
	public String getName() {
		return this.name;
	}
	public int getAge() {
		return this.age;
	}
}
class Student extends Person{//继承类
	private String school;
	public Student(String name,int age,String school) {
		super(name,age);//子类构造函数
		this.school=school;
	}
	public String getSchool() {
		return this.school;
	}
}

public class transfer {
     public static void main(String[] args) {
	        Student stu=new Student("张三",55,"哈工大");
	        System.out.println(stu.getName()+" "+stu.getAge()+" "+stu.getSchool());
    }
}

 二:覆写

主要应用于子类在继承了父类的属性和方法后,自己定义的属性和方法出现了同名的情况。

方法的覆写

class A{//-父类
	public void fun() {
		System.out.println("父类的fun()方法");
		}
	}
class B extends A{//继承类
	
}
public class transfer {
     public static void main(String[] args) {
	      B b=new B();
	      b.fun();
    }
}



//运行结果:父类的fun()方法

class A{//-父类
	public void fun() {
		System.out.println("父类的fun()方法");
		}
	}
class B extends A{//继承类
	public void fun() {
		System.out.println("子类的fun()方法");
		}
}
public class transfer {
     public static void main(String[] args) {
	      B b=new B();
	      b.fun();
    }
}
//运行结果:子类的fun()方法

结论:没有重名时,调用父类,子类和父类有重名函数:调用自己的函数

关键---分析覆写结果时候:
1:观察实例化的是哪个类
2:观察这个实例化的类里面调用的方法是否已经覆写过,否则调用父类的方法

 实例:

 覆写的目的就是子类对父类同样名称方法的一种改进,但是覆写时候必须考虑权限问题
原则:被子类所覆写的方法不能拥有比父类更强的访问控制权限。
(父类public,子类必须public)
一般而言:public>default>protected>private(越右越严) 

注意:父类的private的方法不能被子类覆写,就相当于子类不能直接访问父类的私有属性,如果子类定义了和父类同名private方法,但是不发生覆写,就是普通方法。

子类调用父类同名覆写方法:

class A{//-父类
	public void print() {
		System.out.println("父类print()方法");
	}
}
class B extends A{//继承类
	public void print() {
		super.print();//调用父类print()
		System.out.println("子类fun()方法");
	}
}
public class transfer {
     public static void main(String[] args) {
    	 B b=new B();
 		 b.print();
    }
}

 运行结果:父类print()方法
子类fun()方法

this在子类中用法:

结论:super.方法()只会从父类去查找方法;this.方法()先从子类方法找,找不到再去父类找

属性的覆盖 

 实际开发中,属性一般会封装,所以没有意义,但是如果属性是public 后,那么属性名称相同时会发生覆盖。(哪怕类型不同)

 总结:覆写是为了子类去扩充父类已有方法的功能,覆写要注意访问权限,想调用父类的同名方法加super.

三:final 关键字 

1:final定义的类不可以有子类

 
2:final 定义的方法不能被子类覆写​ 

 一般而言:final类或final方法我们开发中不常用。

3:使用final定义的变量会变成常量,而且定义时候必须加上内容,此后不可更改

 

作用:用变量名称定义常量。注意:常量命名规范:全部大写 如:GOOD,MSG.

公共常量:public static final String MSG="fdgdgd";数据保存在:公共数据区。