一、封装
1. 为什么——高内聚、低耦合
内聚:一个模块内各个元素彼此结合的紧密程度,意味着重用和独立;
耦合:一个软件结构内不同模块之间互连程度的度量,意味着牵一发而动全身。
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用。
2. 是什么
把客观事物封装成抽象概念的类,并且类可以把自己的数据和方法只向可信的类或者对象开放,向没必要开放的类或者对象隐藏信息。简单来说,就是把该隐藏的隐藏起来,该暴露的暴露出来。
3. 怎么实现
实现封装就是控制类或者成员的可见性范围,依赖访问控制修饰符来控制。
4. 体现
- 私有化(private)类的属性,提供公共(public)的get和set方法,对此属性进行获取或修改
- 将类中不需要对外暴露的方法设置为private
- 单例模式中构造器private的了,避免在类的外部创建实例
二、继承
1. 为什么
- 减少代码冗余,提高代码复用性
- 有利于功能的扩展
- 让类与类之间产生“is-a”的关系,为多态的使用提供了前提
2. 是什么
继承描述事物之间的所属关系,这种关系是“is-a”的关系。可见,父类更通用、更一般,子类更具体。子类不是父类的子集,而是对父类的扩展。
3. 怎么实现
// 父类(superClass、超类、基类)
class A{
// A的属性、方法
}
// 子类(subClass、派生类)B继承了A的属性和方法
// 不需要再次声明,B可以直接调用A的属性和方法(访问控制允许的情况下)
// 如A的一个属性为private,B继承了该属性但不能直接使用
class B extends A{
// B的属性、方法
}
class C extends B{
// C的属性、方法
}
- Java中声明的类,若没有显式的声明其父类时,默认继承于java.lang.Object
- Java支持多层继承,如A继承于Object、B继承于A、C继承于B,B是C的直接父类、A是C的间接父类
- Java只支持单继承,即一个子类只能有一个父类,但一个父类可以有多个子类
-
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
4. 重写(override)
子类对父类继承的方法进行覆盖、覆写的操作
class A{
public void method() {
// 实现功能1
}
}
class B extends A{
public void method() {
// 实现功能2
// 对B的实例调用method()方法实现功能2,而非功能1
}
}
- 父类被重写的方法与子类重写的方法的方法名和形参列表必须相同
- 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
- 父类中声明为private的方法不能被子类重写
- 关于返回值
父类返回值类型 | 子类返回值类型 |
void | void |
基本数据类型 | 与父类相同 |
引用数据类型(如类) | 与父类相同或父类返回值类型的子类 |
5. super关键字
super可以理解为“父类的”,可以调用属性、方法、构造器
public class test3 {
int a;
String b;
public test3(int a, String b) {
this.a = a;
this.b = b;
}
public void method1() {
System.out.println("test3-method1" + a + b);
}
}
class t extends test3 {
boolean c;
public t(int a, String b, boolean c) {
// 调用父类构造器
super(a, b);
this.c = c;
}
public void method1() {
System.out.println("t-method1" + a + b + c);
}
public void method2() {
// 调用父类被重写方法
super.method1();
}
public static void main(String[] args) {
t t = new t(1, "iii", false);
t.method1();
t.method2();
}
}
// t-method11iiifalse--iii
// test3-method11iii
三、多态
1. 为什么
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
2. 是什么
一个事物的多种形态。
同一个接口,使用不同的实例而执行不同操作。
3. 怎么实现
前提:
- 要有类的继承关系
- 要有方法的重写(多态仅适用于方法,不适用于属性)
public class A{
// ...
public void m1(){}
}
public class B extends A{
// ...
// 重写父类m1方法
public void m1(){}
}
public class Test{
public static void main(String[] args) {
// 多态性之前的场景
A a = new A();
B b = new B();
// 多态性:子类对象的多样性
A c = new B();
// 多态性的应用
c.m1(); // 虚拟方法调用:编译认为调用A的m1,运行调用B的m1
// 向下转型:使用强制类型转换
// 在转型之前最好用instanceof判断
if(c instanceof B) {
B d = (B)c; // 此时d可以调用B特有的属性和方法
}
}
}
弊端:
对于创建的对象,内存中加载了子类特有的属性和方法,但不能直接调用,如需调用需要向下转型。