一:继承
要点:继承的主要作用和实现,继承的相关限制和使用规则。
继承主要是为了解决代码的重用。
继承的实现
语法: 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";数据保存在:公共数据区。