面向对象三大特征之一(封装,继承,多态)
一:封装
- 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
- 成员变量private,提供对应的getXxx()/setXxx()方法
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性
二:继承
让类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员
格式:public class 子类名 extends 父类名 { }
范例:public class Zi extends Fu { }
Fu:是父类,也被称为基类、超类
Zi:是子类,也被称为派生类
好处和弊端
- 好处:提高了代码的(复用性、维护性),是多态的前提
- 弊端:降低了代码灵活性,增强了代码的耦合性
特点
Java只支持
单继承
,不支持多继承
,但支持多层继承
如果子父类中,出现了
重名的成员变量
,通过就近原则
,会优先使用子类的如果一定要使用父类的,可以通过
super关键字
,进行区分1.多重继承
public class Granddad {
public void drink() {
System.out.println("爷爷爱喝酒");
}
}
public class Father extends Granddad {
public void smoke() {
System.out.println("爸爸爱抽烟");
}
}
public class Mother {
public void dance() {
System.out.println("妈妈爱跳舞");
}
}
public class Son extends Father {
// 此时,Son类中就同时拥有drink方法以及smoke方法
}
2.继承中变量的访问
// 子类局部范围找
// 子类成员范围找
// 父类成员范围找
// 如果都没有就报错(不考虑父亲的父亲…)
class Fu {
int num = 10;
}
class Zi {
int num = 20;
public void show(){
int num = 30;
System.out.println(num);
}
}
public class Demo1 {
public static void main(String[] args) {
Zi z = new Zi();
z.show(); // 输出show方法中的局部变量30
}
}
成员变量访问
-
this
:代表本类对象的引用 -
super
:代表父类存储空间的标识(可以理解为父类对象引用)
方法重写
- 在继承体系中,子类出现了和父类中一模一样的方法声明
- 父类中私有方法不能被重写
- 父类
静态方法
,子类必须通过静态方法进行重写,父类非静态方法
,子类也必须通过非静态方法进行重写 - 子类重写父类方法时,访问权限必须大于等于父类(public > 默认 > 私有)
注意:静态方法不能被重写!如果子类中,也存在一个方法声明一模一样的方法�可以理解为,子类将父类中同名的方法,隐藏了起来,并非是方法重写!
public class Fu {
private void show() {
System.out.println("Fu中show()方法被调用");
}
void method() {
System.out.println("Fu中method()方法被调用");
}
}
public class Zi extends Fu {
/* 编译【出错】,子类不能重写父类私有的方法*/
@Override
private void show() {
System.out.println("Zi中show()方法被调用");
}
/* 编译【出错】,子类重写父类方法的时候,访问权限需要大于等于父类 */
@Override
private void method() {
System.out.println("Zi中method()方法被调用");
}
/* 编译【通过】,子类重写父类方法的时候,访问权限需要大于等于父类 */
@Override
public void method() {
System.out.println("Zi中method()方法被调用");
}
}
构造方法的访问
子类中所有的构造方法默认都会访问父类中无参的构造方法
为什么?
子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
子类初始化之前,一定要先完成父类初始化怎么初始化?
构造方法的第一条语句默认都是:super()this(…) super(…) 必须放在构造方法的第一行有效语句,并且二者不能共存。
三:多态
同一个对象,在不同时刻表现出来的不同形态
多态的前提和体现
- 有继承/实现关系
- 有方法重写
- 有父类引用指向子类对象
多态中成员访问特点
-
构造方法
:同继承一样,子类会通过 super 访问父类构造方法 -
成员变量
:编译看左边(父类),执行看左边(父类) -
成员方法
:编译看左边(父类),执行看右边(子类)
多态中的转型
- 向上转型
从子到父,父类引用指向子类对象 - 向下转型
从父到子,父类引用转为子类对象
好处和弊端
- 好处:提高了代码的扩展性
- 弊端:无法使用子类特有成员
instanceof
如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
变量名 instanceof 类型
- 判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
实例2
class Animal {
public void eat(){
System.out.println("动物吃饭");
}
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Test1Polymorphic {
/*
多态的前提:
1. 要有(继承 \ 实现)关系
2. 要有方法重写
3. 要有父类引用, 指向子类对象
*/
public static void main(String[] args) {
// 当前事物, 是一只猫
Cat c = new Cat();
// 当前事物, 是一只动物
Animal a = new Cat();
a.eat();
}
}
实例2
class Fu {
int num = 10;
public void method(){
System.out.println("Fu.. method");
}
}
class Zi extends Fu {
int num = 20;
public void method(){
System.out.println("Zi.. method");
}
}
public class Test2Polymorpic {
/*
多态的成员访问特点:
成员变量: 编译看左边 (父类), 运行看左边 (父类)
成员方法: 编译看左边 (父类), 运行看右边 (子类)
*/
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.num);
f.method();
}
}