百知教育 - 孙帅 - 08_面向对象的三大特性
01_封装
-
概念:
尽可能 隐藏 对象内部实现细节,控制 对象的修改及访问的 权限。 -
访问修饰符:
private(可将属性修饰为 私有 ,仅本类可见) -
公共访问方法:
- 作用:
提供公共访问方法,以保证数据的 正常录入。 - 命名规范:
赋值:setXXX() //使用方法返回值实现赋值
取值:getXXX() //使用方法返回值实现取值
- 作用:
-
注意:
定义类时,应当将类的 属性 设置为 private ,然后 提供公共访问方法。
02_继承的概念
-
继承的实现:
语法: class 子类 extends 父类{} // 定义子类 时,显示继承父类
-
继承的特点:
java为 单继承 ,一个类只能有一个直接父类(因此,类之间才能形成简单的树状结构),但可以多级继承,属性和方法逐级叠加。
-
代码:
package day9; public class TestInheritance{ public static void main(String[] args){ Dog dog = new Dog(); dog.eat(); } } class Animal{ public void eat(){ System.out.println("eat it"); } public void sleep(){} } class Dog extends Animal{ public void shout(){} }
-
运行结果:
03_访问修饰符
-
父类的哪些属性和方法能 继承 给子类? <==> 子类能 访问 父类的哪些属性和方法?(难理解)
-
访问修饰符 访问范围 继承性
private 本类内部 不可继承
public 公开 可以继承
(default) 本类+同包 同包子类可以继承
protected 本类+同包+子类 可以继承 -
构造方法:
不可继承
-
代码:
package pa; public class A{ private int m1 = 10; int m2 = 20; protected int m3 = 30; public int m4 = 40; }
package pa; public class B extends A{ public void print(){ System.out.println(m1); System.out.println(m2); System.out.println(m3); System.out.println(m4); } }
package pb; import pa.A; public class C extends A{ public void print(){ System.out.println(m1); System.out.println(m2); System.out.println(m3); System.out.println(m4); } }
-
运行结果:
04_组合聚合复用原则
-
LSP (面向对象理论中的里氏代换原则)
内容: 针对父类描述的一句话,将父类换成子类时也必须是成立的。
-
组合/聚合复用原则
内容: 对于违反里氏代换原则的两个类,由于不存在is a关系,所以不能定义继承,可以用 组合 的方式实现类的代码 复用。
-
(组合/聚合复用原则说明)代码:
class TechThief{ public void studyTech(){ //10000 } public void thief(){} } class YKY{ TechThief techThief = new TechThief(); public void studyTech(){ techThief.studyTech(); } }
05_方法覆盖(Override)
-
概念:
子类用特殊的 方法实现 ,替换 掉父类继承给它的方法实现。 -
语法:
方法名相同,参数表相同,返回值类型相同,访问修饰符相同或 更宽。【private, (default), protected, public(最宽)】 -
注意:
当父类中的方法为私有时,因为子类没有继承到,所以不叫方法覆盖,也就不遵循方法覆盖的语法要求。
06_对象构造过程
-
具有继承关系的对象构造过程
例:(父类)A ---- B ---- C(子类)
1) 分配空间
2) 初始化A属性
3) 调用A构造方法
4) 初始化B属性
5) 调用B构造方法
6) 初始化C属性
7) 调用C构造方法 -
super
- 语法: 用在构造方法中,指明 调用父类 哪个 构造方法 ,必须出现在构造方法的 第一行 。
- 理解: 如果一个构造方法的第一行不是super(…), 也不是this(…),默认 为 super();
-
代码:
package day9; public class TestSuper{ public static void main(String[] args){ new B(); } } class A{ public A(){ System.out.println("A()"); } public A(int n){ System.out.println("A(int)"); } } class B extends A{ public B(){ super(20); System.out.println("B()"); } public B(int n){ super(); System.out.println("B(int)"); } }
-
运行结果:
-
思考:
class X{ public X(int i){} } class Y extends X{} /* 编译错误: Y类的定义相当于: class Y extends X{ public Y(){ super(); } } 由于X类中没有无参构造方法,所以会编译错误。 */
07_super引用
-
super.(引用)
- 含义: 指向 父类 对象
- 作用: 用于 访问父类 被遮盖的 属性 或者用于 调用父类 被覆盖的 方法。
-
代码:
package day9; public class TestSuper{ public static void main(String[] args){ Sup sup = new Sup(); sup.invoke(); } } class Super{ public void method(){ System.out.println("Super method"); } } class Sup extends Super{ public void method(){ System.out.println("Sup method"); } public void invoke(){ method(); //Sup method super.method(); //Super method } }
-
运行结果:
08_09_多态的语法
-
子类对象可以赋值给父类引用
-
只能对引用调用其 引用类型 中声明的方法。
1.1 代码解释:package day10; public class TestPloymorphism{ public static void main(String[] args){ Animal a = new Dog(); a.eat(); a.sleep(); a.shout(); } } class Animal{ public void eat(){ System.out.println("Animal eat"); } public void sleep(){ System.out.println("sleep 8 hours"); } } class Dog extends Animal{ public void sleep(){ System.out.println("sleep 6 hours"); } public void shout(){ System.out.println("WangWang"); } } class Cat extends Animal{ }
1.2 运行结果:【编译错误:因为Animal中没有shout()方法】
-
运行时,根据 对象实际类型 ,调用子类覆盖之后的方法。
-
对象类型不变,强制类型转换,用于父类引用赋值给子类引用,但无法改变对象类型。因此,虽然 编译 能够 通过 ,但是 运行 时会 报错 。
3.1 代码解释:package day10; public class TestPloymorphism{ public static void main(String[] args){ Animal a = new Cat(); a.eat(); a.sleep(); //a.shout(); error! Dog d = (Dog)a; d.shout(); } } class Animal{ public void eat(){ System.out.println("Animal eat"); } public void sleep(){ System.out.println("sleep 8 hours"); } } class Dog extends Animal{ public void sleep(){ System.out.println("sleep 6 hours"); } public void shout(){ System.out.println("WangWang"); } } class Cat extends Animal{ }
3.2 运行结果: (编译通过,运行错误:猫的对象类型并没有改变)
-
引用 instanceof 类名<==>“判断引用中的 对象 是不是 类名”, 用作强制类型转换之前进行类型判断,避免类型转换异常。
4.1 代码解释:package day10; public class TestPloymorphism{ public static void main(String[] args){ Animal a = new Dog(); a.eat(); a.sleep(); //a.shout(); error! if(a instanceof Dog){ Dog d = (Dog)a; d.shout(); } } } class Animal{ public void eat(){ System.out.println("Animal eat"); } public void sleep(){ System.out.println("sleep 8 hours"); } } class Dog extends Animal{ public void sleep(){ System.out.println("sleep 6 hours"); } public void shout(){ System.out.println("WangWang"); } } class Cat extends Animal{ }
4.2 运行结果:
-
10_多态的意义
-
多态的作用:
把不同子类的对象,统一 看作 是 父类对象 来处理,屏蔽 了不同子类的 差异 ,使得代码有更好的 通用性 。
-
多态的用法:
- 多态用在 参数 上 m(A a): m方法允许A类或A的某个子类对象作为实参
- 多态用在 返回值 上 A m(): m方法返回的是A类或A的某个子类对象
-
代码:
package day10; public class TestPloy2{ public static void main(String[] args){ /* Dog a0 = new Dog(); Cat a1 = new Cat(); Monkey a2 = new Monkey(); Tiger a3 = new Tiger(); Sheep a4 = new Sheep(); Cock a5 = new Cock(); a0.eat(); a1.eat(); a2.eat(); a3.eat(); a4.eat(); a5.eat(); */ Animal[] as = {new Dog(), new Cat(), new Monkey(), new Tiger(), new Sheep(), new Cock()}; for(int i = 0; i < as.length; i++){ as[i].eat(); } Animal a = buyAnimal(2); Animal b = buyAnimal(3000); } /* static void feed(Dog d){ d.eat(); } static void feed(Cat c){ c.eat(); } ... */ static void feed(Animal a){ a.eat(); } static Animal buyAnimal(int money){ if(money<5) return new Cock(); else if(money<50) return new Cat(); else if(money<200) return new Dog(); else if(money<500) return new Sheep(); else if(money<1000) return new Monkey(); else return new Tiger(); } } class Animal{ public void eat(){} } class Dog extends Animal{ public void eat(){ System.out.println("Dog eats bone"); } } class Cat extends Animal{ public void eat(){ System.out.println("Cat eats fish"); } } class Monkey extends Animal{ public void eat(){ System.out.println("Monkey eats banana"); } } class Tiger extends Animal{ public void eat(){ System.out.println("Tiger eats human"); } } class Sheep extends Animal{ public void eat(){ System.out.println("Sheep eats grass"); } } class Cock extends Animal{ public void eat(){ System.out.println("Cock eats rice"); } }
-
运行结果: