5.3-面向对象特征(二)封装、多态

原作者:无缘
原博客链接:5.3-面向对象特征(二)封装、多态

封装(encapsulation)

封装的作用和含义

我要看电视,只需要按一下开关和换台就可以了。有必要了解电视机内部的结构吗?有必要碰碰显像管吗?制造厂家为了方便我们使用电视,把复杂的内部细节全部封装起来,只给我们暴露简单的接口,比如:电源开关。具体怎么内部实现的,我们不需要操心。

需要让用户知道的暴露出来,不需要让用户了解的全部隐藏起来。这就是封装。

我们程序设计要追求“高内聚,低耦合”。 高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用。

编程中封装的具体优点:

“低耦合”:简化外部调用,便于调用者使用,便于扩展和协作。

“高内聚”:封装细节,便于修改内部代码,提高可维护性。

使用访问控制符,实现封装

JAVA是使用“访问控制符”来控制哪些细节需要封装、哪些细节需要暴露。

5.3-面向对象特征(二)封装、多态_第1张图片
  1. private 表示私有,只有自己类能访问
  2. default表示没有修饰符修饰,只有同一个包的类能访问
  3. protected表示可以被子类访问
  4. public表示可以被所有类访问

封装的使用细节

类的属性的处理:

  1. 一般使用private.(除非本属性确定会让子类继承)
  2. 提供相应的get/set方法来访问相关属性. 这些方法通常是public,从而提供对属性的读取操作。(注意:boolean变量的get方法是用:is开头!)
  3. 一些只用于本类的辅助性方法可以用private,希望其他类调用的方法用public。

【示例1】JavaBean的封装实例

public class Person {
    private String name;
    private int age;
    private boolean flag;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

多态(polymorphism)

多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。 比如:

同样是调用人的“休息”方法。张三是睡觉,李四是旅游,高淇是敲段代码,数学教授是做个数学题。

多态的要点:

  1. 多态是方法的多态,不是属性的多态。
  2. 多态的存在要有3个必要条件:要有继承,要有方法重写,父类引用指向子类对象

【示例2】多态和强制类型转换测试

public class TestPolym {
    public static void main(String[] args) {
        Animal animal = new Dog(); //向上可以自动转型

        //传的具体是哪一个类就调用哪一个类的方法。大大提高了程序的可扩展性。
        //如果没有多态,我们,我们这里要写很多重载的方法。如果增加一种动物,就需要重载一种动物的喊叫方法。非常麻烦。
        //有了多态,只需要增加这个类继承Animal基类就可以了。
        animalCry(new Dog());
        animalCry(new Cat());

        Dog dog = (Dog) animal; //编写程序时,如果想要调用运行时类型的方法,只能进行强制类型转换,不然通不过编译器的检查。

    }

    static void animalCry(Animal a){
        a.shout();
    }
    
}

class Animal {

    public void shout(){
        System.out.println("叫了一声!");
    }
}

class  Dog extends Animal {

    public void shout(){
        System.out.println("旺旺旺!");
    }

    public void seeDoor(){
        System.out.println("看门中....");
    }
}

class Cat extends Animal {
    public void shout() {
        System.out.println("喵喵喵喵!");
    }
}
5.3-面向对象特征(二)封装、多态_第2张图片

Java学习 之 编译时类型和运行时类型

Java中的许多对象(一般都是具有父子类关系的父类对象)在运行时都会出现两种类型:编译时类型和运行时类型,例如:Person person = new Student();这行代码将会生成一个person变量,该变量的编译时类型是Person,运行时类型是Student。

说明一下编译时类型和运行时类型:

Java的引用变量有两个类型,一个是编译时类型,一个是运行时类型,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,会出现所谓的多态。因为子类其实是一种特殊的父类,因此java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,或者被称为向上转型,由系统自动完成。

引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法,因此,编写Java代码时,引用变量只能调用声明该变量所用类里包含的方法。与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性。

引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法,因此,编写Java代码时,引用变量只能调用声明该变量所用类里包含的方法。与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性。

你可能感兴趣的:(5.3-面向对象特征(二)封装、多态)