什么是面向对象,它的三个基本特征:封装、继承、多态

2年前 (2022) 程序员胖胖胖虎阿
185 0 0

什么是面向对象思想?已经学完了java确不知道如何跟别人解释面向对象是什么意思这很常见。让我们一起来回顾下这个奇思妙想~

文章目录

  • 一、面向对象与面向过程
    • 1、什么是面向过程?
    • 2、什么是面向对象?
  • 二、类与对象的关系
    • 1、基本概念
    • 2、类与对象的区别
  • 三、基本特征:封装、继承、多态
    • 1、封装
    • 2、继承
    • 3、多态

一、面向对象与面向过程

现在越来越多的高级语言流行起来了,如大家耳熟能详的c++,python,java等,这些都是基于面向对象的语言
而最最基础的,学校必学的语言----c语言它是属于面向过程的语言。
好了,现在让我们来讨论下这两类语言的区别

1、什么是面向过程?

面向过程:
就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

举例来说,大象装进冰箱需要几步?
什么是面向对象,它的三个基本特征:封装、继承、多态
按照面向过程思想:
第一步:工作人员去打开冰箱门
第二步:把大象塞进冰箱
第三步:工作人员把冰箱门关上
诶,这里我们就看出来了,面向过程就是把一件事按步骤一步一步来实现
用代码表示

    public void openDoor(){}  //开门
    public void putIn(){}       //装冰箱
    public void closeDoor(){}   //关门

依次调用这些方法就完成了

2、什么是面向对象?

对象,就是对问题中的事物的抽象
面向对象:
就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。

用面向对象思想解决大象装进冰箱

大致的了解到了对象这个概念,可以说是对现实事物的一种抽象映射
什么是面向对象,它的三个基本特征:封装、继承、多态
例如在这个事件中:
冰箱作为一个对象;
大象作为一个对象。
冰箱有这些功能:开门、装物体、关门

class fridge{
    public void open(大象){}   //开门
    public void putIn(大象){}  //放进冰箱
    public void close(大象){}  //关门
}
class elephant{
	public void eat(){}   //吃
}

看出来了什么?每个对象是独立的,有属于它自己的功能,只需要专心实现自己的功能就好。所以在建立对象模型阶段,仅仅关注对象有什么的功能,但不考虑如何实现这些功能。

面向对象的好处,就包括有很好的延展性,比如我给大象赋予了一个吃的功能,它通过调用就可以在冰箱里去吃东西。面向对象就是把现实问题抽象为对象,通过调用每个对象的属性或功能去解决问题。

如果我要修改我的需求,把大象换成兔子,我用面向过程是不是得把每个步骤中的大象改为兔子。而用面向对象解决,我甚至可以重新创一个兔子对象,仅仅在调用的时候选择兔子就行了。

二、类与对象的关系

很多人都会创建对象,不就是new嘛,调用对象方法不就是new.方法嘛。结果,有部分人在new类的时候,就下意识的把类当成了对象,那么类到底是不是对象呢?

肯定不是,先给出他们的基本概念

1、基本概念

对象
对象是由数据(描述事物的属性)和作用于数据的操作(体现事物的行为)组成的封装体,描述客观事物的一个实体,是构成系统的基本单元。


类是对一组有相同数据和相同操作的对象的定义,是对象的模板,其包含的方法和数据描述一组对象的共同行为和属性。类是在对象之上的抽象,对象则是类的具体化,是类的实例。类可有其子类,也可有其他类,形成类层次结构。

2、类与对象的区别

1)类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。

2)类是一组具有相同属性和行为的对象的抽象。我们可以将类看做是创建对象蓝图,对象根据这个蓝图去具体实现某个东西。

比如来说,给一张“伞”的蓝图,我们设计出了晴雨伞,剑伞等等,你会发现,这些伞都有相同的行为呀----遮雨
什么是面向对象,它的三个基本特征:封装、继承、多态

所以,类的实例化结果就是对象,而对一类对象的抽象就是类,类描述了一组有相同属性和相同方法的对象。

三、基本特征:封装、继承、多态

1、封装

(一)基本概念
封装(encapsulation)即信息隐蔽。它是指在确定系统的某一部分内容时,应考虑到其它部分的信息及联系都在这一部分的内部进行,外部各部分之间的信息联系应尽可能的少。

(二)四种访问控制级别

  • public:对外公开,访问级别最高
  • protected:只对同一个包中的类或者子类公开
  • 默认:只对同一个包中的类公开
  • private:不对外公开,只能在对象内部访问,访问级别最低
    什么是面向对象,它的三个基本特征:封装、继承、多态

(三)封装使用
1、把尽可能多的东西藏起来,对外提高简洁的接口
比如有半自动洗衣机和一个全自动洗衣机

半自动洗衣机接口有以下方法
①开机
②关机
③放水
④定时
⑤洗涤
⑥排水
⑦脱水

全自动洗衣机有以下方法
①开机
②关机
③设置洗衣机模式
④开始洗衣服,洗完自动关

对比来看,我们就会发现,自动洗衣机把放水、定时、洗涤、排水、脱水等细节,封装到了③设置洗衣机模式里,这样为使用者提供了更加简单易用的接口,所以自动洗衣机会更加方便。

2、把所有属性藏起来
加入某种属性允许外界访问,那么提供访问该属性的公开方法。假如狗类有一个名字、年龄属性,不允许外界直接访问属性,但允许提供get和set方法来访问

class Dogs{
    private String name;  //名字
    private String age;   //年龄
    
    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

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

那么我们把属性设为private私有,把对外界提供设置属性的方法设置为public。

有些人会问,既然是对外公开的,为什么不直接把name,age属性设置为public呢,反而还要通过方法来设置,会不会多此一举?

不会,有以下四个原因:

(一)符合现实外因通过内因起作用的客观规律
假设原来狗就有一个叫“旺财”的名字,是对象本身原主人取的,调用了setName()方法【内因】。好了,领养狗的主人打算给狗换个名字“大黄”,他是使用者,也是调用setName()方法【外因】。

(二)灵活控制属性的读和修改的访问级别
比如我只能让使用者知道这狗狗的名字,但却不允许修改他。那就吧setName()设为private私有,getName()设为public公有。

(三)防止使用者错误修改属性
直接调用类的属性,万一改错了怎么办。所以我们可以在公有方法setName()里面添加限制条件,防止使用者错误修改属性。例如,狗狗的年龄的范围要在0~20期间。

public void setAge(int age) {
    if (age >20 || age < 0){
        throw new IllegalArgumentException("口令不合法");
    }
    else {
        this.age = age;
    }
}

(四)有助于对象封装实现细节
如果上述判断年龄合法的过程我们不想对使用者公开,就把这个过程用private封装成一个“透明”的方法。这个判断年龄合法的过程对使用者是透明的。

与封装具有相同含义的一个概念就是透明。对象封装实现细节,也就意味着对象的实现细节对使用者是透明的。透明在这里理解为“看不见”

public void setAge(int age) {
        isLegal();   //判断是否合法
        this.age = age;
    }

private void isLegal(){
    if (age >20 || age < 0){
        throw new IllegalArgumentException("口令不合法");
    }
    else return;
}

2、继承

继承:让某个类型的对象获得另一个类型的对象的属性和方法。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

(一)语法

class A extends B{}

一共继承了哪些东西呢?这要分两种情况

  • 当A和B在同一包下,A继承了B中public、protected和默认访问级别的成员变量和成员方法
  • 当A和B不在同一包下,A继承了B中public、protected成员变量和成员方法

(二)继承父类成员变量/方法
hanqishi继承了父类Dog

class Dog{
    public String name="小白";
    public void say(){
        System.out.println("汪汪汪");
    }
}
//哈奇士
class haqishi extends Dog {
    public void test(){
        System.out.println(name);
        say();
    }
}

调用haqishi的test()方法,测试如下

小白
汪汪汪

测试结果:子类haqishi继承了父类的成员变量和成员方法

(三)重写父类方法
子类haqishi重写父类Dog的say方法

class Dog{
    public String name="小白";
    public void say(){
        System.out.println("汪汪汪");
    }
}
//哈奇士
class haqishi extends Dog {
    @Override
    public void say() {
        //super.say();    继承父类原有方法
        System.out.println("哈哈哈");
    }
}

调用子类say方法,测试如下:

哈哈哈

(四)重载父类方法
重载方法必须满足以下条件:
1、方法名相同
2、方法的参数类型、个数、顺序至少有一项不同
3、方法的返回类型可以不同
4、方法的修饰符可以不相同

class Dog{
    public String name="小白";
    public void say(){
        System.out.println("汪汪汪");
    }
}
//哈奇士
class haqishi extends Dog {
   //重载 改变参数
    public void say(String name) {
        System.out.println(name+"汪汪汪");
    }
	//重载 改变参数+返回值
    public int say(int age) {
        System.out.println("汪汪汪"+age);
        return age;
    }
}

分别调用
haqishi h = new haqishi();
h.say();
h.say(“哈奇士”);
h.say(6);
结果如下:

汪汪汪
哈奇士汪汪汪
汪汪汪6

3、多态

多态:对于同一个行为,不同的子类对象具有不同的表现形式。多态存在的3个条件:
1)继承 2)重写 3)父类引用指向子类对象。

public class extend {
    public static void main(String[] args) {
        Animal a = new Dog();
        Animal b = new Cat();
        a.say();
        b.say();
    }
}

abstract class Animal {
    abstract void say();
}
//猫
class Cat extends Animal{
    public String name="小黑";
    public void say(){
        System.out.println("喵喵喵");
    }
}
//狗
class Dog extends Animal{
    public String name="小白";
    public void say(){
        System.out.println("汪汪汪");
    }
}

运行结果

汪汪汪
喵喵喵

理解多态
在这个运行环境中,引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。Java虚拟机会根据引用变量指向的对象来调用该对象的指定方法,这种运行机制被称为动态绑定

参考文献:《Java面向对象编程(第2版)》- 孙卫琴

相关文章

暂无评论

暂无评论...