1. 重温面向对象
面向对象是一种解决问题的思想,它把计算机程序看作是各种对象组合起来的。每个对象都有自己的数据(属性)和行为(方法),主要依靠对象之间的交互来解决和实现问题。Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。
2. 继承
2.1 什么是继承
继承专门用来进行共性的提取,实现代码的复用。继承是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样的类是派生类(子类)。
2.2 extends关键字
extends关键字用来表示类之间的继承关系。
```java
修饰符 class 子类 extends 父类{
//...
}
```
注意:
1.子类会将父类中的成员变量或者成员方法继承到子类中
2.子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了。
2.3 父类成员的访问
2.3.1 子类访问父类的成员属性
1.子类和父类不存在同名的成员变量
Animals作为父类(基类)
```java
public class Animals {
int legs;
int eyes;
}
```
Dog 作为子类(派生类)
```java
public class Dog extends Animals {
String type;
public void method(){
legs=4;//访问从父类继承下来的a
eyes=2;//访问从父类继承下来的b
type="犬科";//访问自己的成员c
}
}
```
2.子类和父类成员变量同名
Base作为父类(基类)
```java
public class Base {
int a;
int b;
int c;
}
```
Derived作为子类(派生类)
```java
public class Derived extends Base{
int a;//与父类中的成员名相同,且类型相同
char b;//与父类的成员名相同,但类型不同
public void method(){
a=100;//访问自己的a
b=101;//访问自己的b
c=102;//访问从父类继承下来的c
}
}
```
在子类方法中或者子类对象访问成员时:
1.如果访问的成员变量子类中有,则优先访问子类自己的成员变量。
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的成员变量。
成员变量访问遵循就近原则,自己优先自己的,如果没有则向父类中找。
2.3.2 子类访问父类的成员方法
1.成员方法名字不同
Base作为父类(基类)
```java
public class Base {
public void methodA(){
System.out.println("Base中的methodA方法");
}
}
```
Derived作为子类(派生类)
```java
public class Derived extends Base{
public void methodB(){
System.out.println("Derived中的methodB方法");
}
public void methodC(){
methodB();//访问自己的成员方法
methodA();//访问父类继承的成员方法
}
}
```
2.成员方法名字相同
Base作为父类(基类)
```java
public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA方法");
}
public void methodB(){
System.out.println("Base中的methodB方法");
}
}
```
Derived作为子类(派生类)
```java
public class Derived extends Base{
int a;
char b;
public void methodA(int a){
System.out.println("Derived中的methodA方法");
}
public void methodB(){
System.out.println("Derived中的methodB方法");
}
public void methodC(){
//对于同名的成员变量,直接访问,访问的都是子类的
a=100;//等价于:this.a
b=101;//等价于:this.b
//当子类和父类的成员变量名字相同时,通过super关键字访问从父类继承的成员变量
super.a=200;
super.b=201;
//子类和父类的方法构成重载的方法,直接通过参数列表的区别访问父类和子类
methodA();
methodA(20);
//当子类和父类的成员方法同名时,如果想在子类中访问重写的父类方法,需要借助super关键字
methodB();//访问自己的成员方法
super.methodB();//访问父类的成员方法
}
}
```
在子类方法中,如果想要明确访问父类成员时,借助super关键字即可
super的一些注意事项:
只能在非静态方法中使用
在子类方法中,访问父类的成员变量和方法
2.4 super和this
2.4.1 super关键字
super关键字是一个特殊的引用,它指向当前对象的直接父类对象。super可以用来访问父类的属性,方法和构造器。
2.4.2 this关键字
this关键字是一个特殊的引用,它指向当前对象的引用,及当前对象的上下文。this可以访问当前对象的属性,方法和构造器。
super和this的相同点 :
1.两者都是Java关键字。
2.只能在类的非静态方法中使用,用来访问非静态成员方法和字段。
3.在构造方法中调用,必须是构造方法中的第一条语句,并且不能同时存在。
super和this的不同点 :
1.this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用。
2.在非静态方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性。
3.在构造方法中,this()用于本类的构造方法,super()用于调用父类构造方法,两种调用不能同时在构造方法中出现。
4.构造方法中一定会存在super()的调用,用户没有写构造方法编译器也会增加,但是this()不写就没有编译器不会增加。
2.5 子类的构造方法
构造函数是用来初始化的 。
子类对象构造时,需要先调用父类的构造方法,然后执行子类的构造方法。
1.无参构造函数
语法格式
```java
public 类名() {
}
```
2.有参构造函数
语法格式
```java
public 类名(类型 参数1, 类型 参数2) {
this.成员变量1 = 参数1;
this.成员变量2 = 参数2;
}
```
通过例子观察继承中子类和父类构造函数执行的先后顺序。
父类Base
```java
public class Base {
public Base() {
System.out.println("执行Base的无参构造函数");
}
}
```
子类Derived
```java
public class Derived extends Base{
public Derived() {
System.out.println("执行Derived的构造函数");
}
}
```
测试函数Test
```java
public class Test {
public static void main(String[] args) {
Derived derived=new Derived();
}
}
```
运行结果:
在子类构造方法中,没有写任何关于父类构造的代码,但是却执行了父类的构造函数,而且是先执行父类的构造函数,后执行子类的构造函数,这是因为:子类对象中的成员是有两部分组成的,教父类继承下来的以及子类新增加的部分。父子,肯定是现有父再有子,所以在构造子类对象时,先调用父类的构造方法,将父类继承下来的成员构造完成,然后再调用子类自己的构造方法,将子类的成员初始化完成。
注意 :
1.若父类显示定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用父类构造方法。
2.如果父类的构造方法是带参数的,此时需要用户为子类定义构造方法,并且子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3.在子类构造方法中,super()调用父类时,必须是子类构造函数中的第一条语句。
4.super()只能在子类构造方法中出现一次,并且不能和this同时出现。
2.6 protected关键字
在上篇文章中我们没有涉及到的访问限定符protected,我们在此进行讨论。
Java中引入访问限定符,主要用来限定类或类中成员能否在类外或者其他包中被访问。
2.7 继承方式
注意:Java不支持多继承!!!
2.8 final关键字
final关键字用来修饰变量和成员方法以及类
1.修饰变量和字段,表示常量不可以进行修改
```java
final int a=99;
a=100;//编译错误
```
2.修饰类,表示此类不能被继承
```java
final public class A{
...
}
public class B extends A{
...
}//编译错误
```
3.修饰方法:表示该方法不能被重写
```java
public class A{
public final void show(){
System.out.println("haHahA");
}
}
public class B extends A{
public void show()//编译错误
}
```