文章目录
3.3 POP三大特征
3.3.1 封装
概念
把类的信息隐藏到类的内部, 不允许外部程序直接访问, 而是通过该类的提供的内部方法对隐藏的信息进行访问与操作.
好处
- 隐藏了类的实现细节.
- 只能通过规定的内部方法访问.
- 方便修改.
- 方便加入控制语句.
应用(具体体现)
public class Person extends Object{
//私有权限, 不允许外部直接访问
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 name;
}
public int getAge() {
return age;
}
}
this关键字
this 代表 正在访问当前类的对象.
静态方法中无法使用this关键字,
public class Person {
private String name;
private int age;
private String sex;
public Person(String name, int age, String sex) {
/**
* this用来区分 成员变量 和 参数
* this.name 表示成员变量
* name 表示参数
*/
this.name = name;
this.age = age;
this.sex = sex;
System.out.println("父类构造方法 2 ");
}
public void setName(String name) {
this.name = name; //调用属性 this表示当前正在访问的对象
}
public void main(String[] args){
this.setName("tom"); //调用方法 this表示当前正在访问的对象
}
}
3.3.2 继承
概念
继承是从已经存在的类中派生出新的子类 , 新的子类能继承祖先类中的所有的非私有的属性和方法 , 并扩展出新的属性与方法(能力)
- java中的继承关系用关键字extend来表示
- java不允许多继承, 子类只能继承一个父类,
- 子类能继承祖先类中的所有的非私有的属性和方法
优点
提高了代码的可重用性和可扩展性(重写)
何时使用继承呢?(应用场景)
符合is- a关系 , 比如猫是动物, 狗是动物 , 猫,狗都有一个共同点是动物.
可以将 猫和狗 共有的属性和行为提取出来放入一个类中, 这个类便是动物类.
猫和狗就都可以继承自动物类.
继承形式
// [访问权限修饰符][修饰符] 子类名 extend 父类名 {}
public class Student extends Person {}
子类对象可以直接调用父类的非私有的方法和属性, 提高代码的复用性
继承的传递
如果 A类继承B类, 而B类继承C类. 那么A就相当于继承了B类和C类的所有的方法和属性.
java中每个类都会默认继承Object类,
Object类是所有类的父类(基类);
继承的构造方法
调用子类构造方法时总是默认调用父类的无参构造方法.
public Student() { //super() 默认存在 你不写也会存在
System.out.println("子类构造方法");
}
也可以自己用super关键字去主动调用父类的任何构造方法.
但super()必须放在构造方法的开头第一行
public Student() {
super(); // 默认存在 你不写也会存在
System.out.println("子类构造方法");
}
public Student(String name, int age, String sex) {
super(name, age, sex);//主动调用父类的构造方法
System.out.println("子类构造方法 2 ");
}
关键字 | 含义 |
---|---|
super | 代指父类 |
this | 代指当前正在访问类的对象 |
重写override
当父类中的方法不能满足子类的需求时, 子类就可以重写父类的方法, 来扩展子类功能,
重写规则:
-
方法名, 参数必须一样
-
返回值的类型必须一样
-
修饰符必须一样
即与父类方法的结构一样
public void eat(){
System.out.println("学生去食堂吃饭");
super.eat(); // 调用父类中的方法时,不用放在第一行
}
类之间的关系
关联关系
“有” , “has - a” 的关系, 指在一个类中把另一个类作为属性的类型使用
public class Student extends Person {
/**
* 关联关系
* 单向关联: A类关联了B类 , 比如 人有手机 .
* 双向关联: A类关联了B类 , B类也关联了A类 . 比如说 人有手机 , 手机也有"拥有者"
*
* 关联的多重性 (和数据库中表的联系很像 )
* 1 对 1 关系 比如 一个手机 只能有一个人使用
* 1 对 多 关系 比如 一个人 能使用 多部手机
*/
private Mobile mobile; // 关联关系 1: 1
private List<Mobile> moblieList; // 1: n 数组 集合
}
一对多关系要用到数组或集合.
依赖关系
“使用”, “use-a” 的关系 , 指一个类被另一个类中的方法使用了 .
比如 人 使用 手机 打电话 .
public class Student extends Person {
/**
* 依赖关系
* 应用场景: 1. 作为方法照中的参数使用 ,
* 2. 直接在方法中使用 .
*/
public void call(Mobile mobile){ // 方法参数
Mobile mobile1 = new Mobile(); // 在方法中直接使用
return;
}
}
总结
关联关系是“has”的关系.
依赖关系是“use”的.
A关联B , B在A中作为属性的类型存在, 称为has关系.
A依赖B , B在A中作为方法参数存在, 称为use关系
3.3.3 多态
概念
同一事物, 在不同时刻下表现出不同的状态 .
多态存在的三个条件
- 要有继承(前提)
- 要有重写(前提)
- 父类引用指向子类对象 Animal animal = new Dog();
编译期和运行期
Animal animal = new Dog();
编译期就是我们用工具写代码的时候, 运行期就是程序运行的时候 .
编译期 animal 是 Animal类型的引用变量, 可以访问父类Animal中的属性和方法 , 但不能访问子类的方法与属性.
/**
* eat() 是父类Animal和子类Dog中共有的方法.
* sleep() 是子类Dog中的专有方法.
*/
Animal animal = new Dog(); //Animal类型的引用变量指向Dog的对象
animal.eat();
animal.sleep(); //报错 不能访问子类中的属性和方法 ,
运行期, 因为Animal是Dog的父类 , 所以可以用父类引用指向子类对象 , 所以此时引用变量animal 里的对象是Dog子类的实例化对象.
多态环境下成员方法的调用
编译期看左边,运行期看右边
class Animal{
void show() {
System.out.println(“Anmial");
}
}
class Dog extends Animal{
void show() {
System.out.println(“cat");
}
}
Animal animal = new Dog()
animal.show()
//虽然是Animal类型的引用变量, 但内在其实是Dog类型的对象,所以调用的是子类Dog中的方法
虽然是Animal类型的引用变量, 但内在其实是Dog类型的对象,所以调用的是子类Dog中的方法
多态环境下静态方法的调用
编译和运行都看左边
class Animal{
static void show() {
System.out.println(“Anmial");
}
}
class Dog extends Animal{
static void show() {
System.out.println(“cat");
}
}
Animal animal = new Dog()
animal.show() //调用的是动物类Animal中的静态成员方法。
//虽然是Animal类型的引用变量, 但内在其实是Dog类型的对象,
//但静态方法是属于类的, 引用变量是Animal类型的, 所以调用的是Animal中的静态方法
多态环境下成员变量的调用
编译和运行都看左边
class Animal{
int num = 3;
}
class Cat extends Animal {
int num = 4;
}
Animal x = new Cat()
x.num; //调用的是父类中的成员变量,
// 要想访问子类的属性, 要向下转型成子类的类型, 然后就可以访问子类中的属性了.
//变量不存在被子类覆写这一说法,只有方法存在覆写。
方法参数具有多态性
方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象
class Animal{
void eat() {}
}
class Cat extends Animal{
void eat() {}
}
class Dog extends Animal{
void eat(){}
}
main(){
Animal animal = new Dog();
method(animal); //狗吃
animal = new Cat();
method(animal); //猫吃
}
//方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象
method(Animal animal){
animal .eat();
}
向上转型
将子类对象提升到父类类型.
/**
* eat() 是父类Animal和子类Dog中共有的方法.
* sleep() 是子类Dog中的专有方法.
*/
Animal animal = new Dog(); // 将Dog对象提升到Animal类型
animal.eat(); //只能使用父类中的方法
animal.sleep(); //报错!不能使用子类中的方法
提高程序的扩展性
向下转型
将父类类型下降到子类对象
/**
* eat() 是父类Animal和子类Dog中共有的方法.
* sleep() 是子类Dog中的专有方法.
*/
Animal animal = new Dog();
if (animal instanceof Dog){
System.out.println("true");
Dog dog = (Dog) animal; //将Animal类型下降到Dog类对象
dog.eat();
dog.sleep();//子父类中的方法都可以使用
}else {
System.out.println("false");
}