目录

雪月书韵茶香

昨夜西风凋碧树,独上高楼,望尽天涯路


X

面向对象编程之封装继承多态

面向对象编程之封装继承多态

封装

封装概述(What)

面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。封装可以被认为是一个保护屏障,防止该类代码和数据被其他类随意访问。要访问该类数据,必须通过指定的方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。

封装原则:将属性隐藏起来,若要访问某个属性,提供公共方法对其访问

封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问

为什么要使用封装(Why)

不使用封装的代码

要解决上面的设计缺陷,我们就可以使用封装.

生活中,我们要看电视,只需要按一下开关和换台就可以了.我们没有必要了解电视机内部结构.

隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用,从而提高系统的可扩展性、可维护性

我们程序设计要追求"高内聚、低耦合"

高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉

低耦合:仅暴露少量的方法给外部使用

封装的优点:

  • 只能通过规定方法访问数据
  • 方便修改实现
  • 隐藏类的实现细节
  • 方便加入控制语句
  • 提高系统的可扩展性、可维护性

如何使用封装(How)

class Dog {
    private String name = "旺财"; // 昵称
    private int health = 100; // 健康值
    private int love = 0; // 亲密度
    private String strain = "拉布拉多犬"; // 品种
    public int getHealth() {
        return health;
    }
    public void setHealth (int health) {
        if (health > 100 || health < 0) {
            this.health = 40;
            System.out.println("健康值应该在0和100之间,默认值是40");
        } else
            this.health = health;
    }
// 其它getter/setter方法
}

继承

继承概述(What)

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要
继承那一个类即可

其中,多个类可以称为子类,单独那一个类称为父类超类(superclass) 或者基类

继承描述的是事物之间的所属关系,这种关系是: is -a 的关系。

例如,图中狗 猫 人,哺乳动物属于动物。

可见,父类更通用,子类更具体。我们通过继承,可以使多种事物之间形成一种关系体系.

为什么使用继承(Why)

看如下这两个类图有什么问题?

使用继承优化后

image-20201109161033068

类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模

提高代码的复用性!

我们在编写代码时候子类继承父类用到的关键字是extends,它的中文意思是"扩展".子类是父类的扩展

对于被进程的类不同的叫法如下

超类、父类、基类、派生类

如何使用继承(How)

使用继承

  • 编写父类
class Pet{
    //公共的属性和方法
}
  • 编写子类
    class Penguin extends Pet{
        //海豚继承了宠物类 
        //海豚特有的属性和方法
    }
    

当子类需要访问父类中被子类覆盖的方法或属性时候,可以通过super关键字来实现

super是直接父类对象的引用.

子类可以随意调用父类的普通方法,没有顺序限制.

任何类的构造函数中,若是构造函数的第一行代码没有显式 的调用super(...),那么Java默认都会调用super();作为父类的初始化函数.

public class Test {
    public static void main(String[] args) {
        new ChildClass().f();
    }
}
class FatherClass {
    public int value;
    public void f(){
        value = 100;
        System.out.println
                ("FatherClass.value="+value);
    }
}
class ChildClass extends FatherClass {
    public int value;
    public void f() {
        super.f();
        value = 200;
        System.out.println
                ("ChildClass.value="+value);
        System.out.println(value);
        System.out.println(super.value);
    }
}

super 总结

  • super关键字来访问父类成员
  • super只能出现在子类的方法和构造方法中
  • super调用构造方法时,只能是第一句
  • super和this不能同时出现在构造方法中
  • super不能访问父类的private成员
  • super和this都不能在static方法中

方法重写

使用继承后效果

方法的重写(override)

  • 在子类中可以根据需要对父类中继承来的方法进行重写
  • 重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型
  • 重写方法不能使用比被重写方法更严格的访问权限.(由于多态)
public class TestOverride {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.shout();
        Dog dog = new Dog();
        dog.shout();
    }
}
class Animal{
    void shout(){
        System.out.println("发出声音! ");
    }
}
class Dog extends Animal {
    void shout(){
        System.out.println("旺旺旺! ");
    }
}

重写(小结)

构造方法也会被重写么?

方法重写规则

  • 方法名相同
  • 参数列表相同
  • 返回值类型相同或是其子类
  • 访问权限不能严于父类

方法重载与重写区分

| | 位置 | 方法名 | 参数表 | 返回值 | 访问修饰符 |
| - | - | - | - | - | - |
| 方法重写 | 子类 | 相同 | 相同 | 相同或是其子类 | 不能比父类更严格 |
| 方法重载 | 同类 | 相同 | 不相同 | 无关 | 无关 |

如何理解继承(How)

子类访问父类成员

  • 访问父类构造方法

    super(); //在子类构造方法中调用必须是第一句
    super(name);
    
  • 访问父类属性

    super.name
    
  • 访问父类方法

    super.print()
    

    子类可以继承父类所有资源么?

    多重继承关系的初始化顺序是怎么样的?(☆☆☆)

    image-20201109163922843

public class TestExtends {
    public static void main(String[] args) {
        Mammal m1 = new Mammal();
        m1.puru();
        m1.eat();
    }
}
class Animal {
    String eyes="眼睛";
    String name="无名";
    public void eat(){
        System.out.println("动物吃东西! ");
    }
}
class Mammal extends Animal {
    //哺乳
    public void puru(){
        eyes= "嘴巴";
        System.out.println("小动物吃奶! ");
    }
}

继承(小结)

  • 通过继承可以简化类的定义,实现代码的重用
  • 子类继承父类的成员变量和成员方法,但不继承父类的构造方法
  • Java中只有单继承,没有C++那样的多继承.多继承会引起混乱,使得继承链过于复杂,系统难以维护.就像我们在现实生活中,如果你有多个父母亲,那将是无法想象的混乱世界.多继承,就是为了实现代码的复用性,却引入了复杂性,使得系统之间的关系混乱.
  • Java中的多继承,可以通过接口来实现.
  • 如果定义一个类时,没有调用extends,则它的父类是:java.lang.object. (万物皆对象)

多态 polymorphism

多态概述(What)

多态是继封装、继承之后,面向对象的第三大特性。

生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

定义: 多态是指同一行为,具有多个不同表现形式.

多态性是OOP中的一个重要特性,主要是用来实现动态联编的,换句话说就是程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了. 这对于大型系统来说提高系统的灵活性和扩展性至关重要.

为什么要使用多态(Why)

使用多态的好处?

多态可以减少类中代码量,可以提高代码 的可扩展性和可维护性

引用变量的两种类型:(补充)

  • 编译时类型 (模糊一点,一般是一个父类) 由声明时类型决定
  • 运行时类型 (运行时,具体是哪个子类就是哪个子类) 由实际对应的对象类型决定

如何实现多态

实现多态的两种方式

  • 使用父类作为方法形参实现多态
  • 适用父类作为方法返回值实现多态

多态存在的三个必要条件:

  • 要有继承
  • 要有方法重写
  • 父类引用指向子类对象

多态实例代码:

class Animal {
    int age=10;
    public void shout(){
        System.out.println("叫了一声! ");
    }
}
class Dog extends Animal {
    int age=28;
    public void shout() {
        System.out.println("旺旺旺! ");
    }
    public void gnawBone(){
        System.out.println("我在啃骨头");
    }
}
class Cat extends Animal {
    int age=18;
    public void shout() {
        System.out.println("喵喵喵喵! ");
    }
}
public class TestPolym {
    public static void main(String[] args) {
        Animal animal = new Dog(); //向上可以自动转型
        System.out.println(animal.age); //属性调用时,仍然是基类的属性。属性没有多态!
// animal.shout();
        animalCry(new Dog());
//传的具体是哪一个类就调用哪一个类的方法。大大提高了程序的可扩展性。
//如果没有多态,我们这里需要写很多重载的方法。如果增加一种动物,就需要重载一种动物的喊叫方法。非常麻烦。
//有了多态,只需要增加这个类继承Animal基类就可以了。
        animalCry(new Cat());
        Dog dog = (Dog) animal; //编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。
        dog.gnawBone();
        System.out.println(dog instanceof Animal);
        System.out.println(animal instanceof Cat);
        System.out.println(animal instanceof Dog);
    }
    static void animalCry(Animal a){
        a.shout();
    }
}

标题:面向对象编程之封装继承多态
作者:shuaibing90
版权声明:本站所有文章除特别声明外,均采用 CC BY-SA 4.0转载请于文章明显位置附上原文出处链接和本声明
地址:https://xysycx.cn/articles/2020/11/09/1604921103906.html
欢迎加入博主QQ群点击加入群聊:验证www.xysycx.cn