LongJL 发表于 2021-7-10 21:50

【自学笔记】 Java基础 - 面向对象(二)三大特征

本帖最后由 LongJL 于 2021-7-11 12:26 编辑

# 面向对象的三大特征
面向对象的三大特征分别是:封装、继承、多态

## 封装
封装在Java中的体现:
      1.方法就是一种封装
      2.关键字private 也是一种封装
      3.封装就是将一些细节信息隐藏起来,对外接不可见

```Java
      public class method {
      public static void main(String[] args) {
            int[] array= {5 , 15 , 20 , 25};
            int max = getMax(array);
            System.out.println("最大值:" + max);

      }
      //传入数组,返回其中的最大值
      public static int getMax(int[] array){
            for(int i = 1 ; i < array.length; i++) {
                if(array > max) {
                  max = array;
                }
            }
            return max;
      }
    }
```
```Java
public class Student {
    private String name; //自己的名字

    public String getName(){
      return age;
    }

    public String setName(String name){
      this.name = name;
    }
}
public class Demo1Person {
    public static void main(String[] args){
      Student student1 = new Student();
      student1.setAge(20);

      Student student2 = new Student();
      student2.setAge(22);
    }
}
```

## 继承
### 概述:
      继承就要解决的问题就是"共性抽取"。
      特点:
                1. 子类可以拥有父亲的"内容"。
            2. 子类还可以拥有自己专有内容。
            3. Java语言是【单继承】的。
                  解释:
                        一个类的**直接**父类只能由一个。
            4. Java语言可以多级继承
            5. 一个子类的父类是唯一的,但是一个父类可以拥有很多子类。
                  备注:
                        1.继承是多态的前提,如果没有继承,就没有多态。
                  2.在继承的关系中,"子类就是一个父类",也就是说,子类可以当作父类看待
                例如:
                  父类是员工,子类是讲师,那么"讲师就是一个员工"。关系:is~a
            3.在父子类得继承当中,如果成员变量重名,则创建子类对象时,访问得方式有俩种:
                  - 直接通过子类对象访问成员变量:
                        等号左边是谁,就优先访问谁,没有则向上查找。
                - 间接通过成员方法访问成员变量;
                        方法属于谁,就优先用谁,没有则向上找。
            4.区分子类方法中重名的三种
                  局部变量:直接写
                本类的成员变量:this.成员变量名;
                父类的成员变量: super.成员变量名;
            5.继承中成员方法的访问特点
                  在父子类的继承关系当中,创建子类对象,访问成员方法的规则
                        创建的对象是谁,就优先用谁,如果没有在向上查找
                注意事项:
                  无论是成员方法还是成员变量,如果没有都是向上查找,绝对不会向下找子类的。
            6.继承中方法的覆盖重写
                  概念:
                        重写( overRead ):
                            在继承关系当中,方法的名称一样,参数列表也一样
                        备注:
                            重载( overLoad ):方法名称一样,参数列表不一样
                            重写( overRead ):方法名称一样,参数列表一样
                特点:
                        创建的是子类对象,就优先使用子类方法。
                注意事项:
                        - 必须保证父子类之间的方法名称一致,参数列表也相同
                            @Override:写在方法前面,用来检测是不是有效的正确的覆盖重写
                        这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。
                  - 子类方法的返回值必须小于等于父类方法的返回值范围。
                            前提:Object类是所有类的公共最高父类(祖宗类):
                              java.lang.String就是Object的子类。
                  - 子类方法的权限必须【大于等于】父类方法的权限修饰符。
                            前提:public > protected > (default) > private
                        备注:(default)不是关键字default,而是什么都不写,留空。
                7.继承中构造方法的访问特点:
                  - 子类构造方法的当中,有一个默认的隐含的"super();"调用,所以一定是先调用父类构造,后执行的子类构造
                  - 子类构造可以通过super关键字来调用父类重载构造。
                - super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
                总结:子类必须调用父类构造方法,不写默认第一行也是super,写了则用写的指定super调用,super只能由一个。还必须是第一个
                8.super关键字的三种用法
                  - 在子类的成员变量中,访问父类的成员变量。
                - 在子类的成员方法中,访问父类的成员方法。
                - 在子类的构造方法中,访问父类的构造方法。
                9.super用来访问父类内容,this用来访问本类内容。
                10.this关键字的三种用法
                  1.在本类的成员方法中,访问本类的成员变量。
                2.在本类的成员方法中,访问本类的另一个成员方法
                3.在本类的构造方法中,访问本类的另一个构造方法
                     例如:
                              ```Java
                              public class FU{
                            public Fu(){
                              this(123); //本类的无参构造,调用本类的有参构造。
                        }
                        public Fu(int num){
      
                        }
                              }
                              ```
                  注意:
                            1.this(...)调用也必须是方法的第一个语句,唯一一个。
                        2.super和this俩个构造调用,不能同时调用


### 格式:
```Java
public class 父类名称{
      ...
}

public class 子类名称 extends 父类名称 {
      ...
}
```
### 案例:
```Java
public class People {
    public String name; // 姓名
    public int age; // 年龄
    public String sex; // 性别
    public String sn; // 身份证号

    public People(String name, int age, String sex, String sn) {
      this.name = name;
      this.age = age;
      this.sex = sex;
      this.sn = sn;
    }

    public String toString() {
      return "姓名:" + name + "\n年龄:" + age + "\n性别:" + sex + "\n身份证号:" + sn;
    }
}

public class Student extends People {
    private String stuNo; // 学号
    private String department; // 所学专业

    public Student(String name, int age, String sex, String sn, String stuno, String department) {
      super(name, age, sex, sn); // 调用父类中的构造方法
      this.stuNo = stuno;
      this.department = department;
    }

    public String toString() {
      return "姓名:" + name + "\n年龄:" + age + "\n性别:" + sex + "\n身份证号:" + sn + "\n学号:" + stuNo + "\n所学专业:" + department;
    }
}

public class Teacher extends People {
    private int tYear; // 教龄
    private String tDept; // 所教专业

    public Teacher(String name, int age, String sex, String sn, int tYear, String tDept) {
      super(name, age, sex, sn); // 调用父类中的构造方法
      this.tYear = tYear;
      this.tDept = tDept;
    }

    public String toString() {
      return "姓名:" + name + "\n年龄:" + age + "\n性别:" + sex + "\n身份证号:" + sn + "\n教龄:" + tYear + "\n所教专业:" + tDept;
    }
}
public class PeopleTest {
    public static void main(String[] args) {
      // 创建Student类对象
      People stuPeople = new Student("王丽丽", 23, "女", "410521198902145589", "00001", "计算机应用与技术");
      System.out.println("----------------学生信息---------------------");
      System.out.println(stuPeople);

      // 创建Teacher类对象
      People teaPeople = new Teacher("张文", 30, "男", "410521198203128847", 5, "计算机应用与技术");
      System.out.println("----------------教师信息----------------------");
      System.out.println(teaPeople);
    }
}
运行结果:
----------------学生信息---------------------
姓名:王丽丽
年龄:23
性别:女
身份证号:410521198902145589
学号:00001
所学专业:计算机应用与技术
----------------教师信息----------------------
姓名:张文
年龄:30
性别:男
身份证号:410521198203128847
教龄:5
所教专业:计算机应用与技术
```


继承的优缺点
在面向对象语言中,继承是必不可少的、非常优秀的语言机制,它有如下优点:
- 实现代码共享,减少创建类的工作量,使子类可以拥有父类的方法和属性。
- 提高代码维护性和可重用性。
- 提高代码的可扩展性,更好的实现父类的方法。

自然界的所有事物都是优点和缺点并存的,继承的缺点如下:
- 继承是侵入性的。只要继承,就必须拥有父类的属性和方法。
- 降低代码灵活性。子类拥有父类的属性和方法后多了些约束。
- 增强代码耦合性(开发项目的原则为高内聚低耦合)。当父类的常量、变量和方法被修改时,需要考虑子类的修改,有可能会导致大段的代码需要重构。


## 多态
### 前提:
      extends继承或者implements实现,是多态性的前提。
      一个对象拥有多种形态,也就是:对象的多态性。
### 概念:
      代码当中体现多态性,其实就是一句话,父类引用指向子类对象。
### 格式:
      父类名称 对象名 = new 子类名称();
      或者:
      接口名称 对象名 = new 实现类名称();
访问成员变量的俩种方式:
      1.直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上查找。
      2.间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上查找。
访问成员方法的方式:
      父子都有,优先子类
注意:
      成员方法:编译看左边,运行看右边。
      成员变量:编译看左边,运行还看左边。
使用多态的好处:
      无论右边new的时候换成哪个子类对象,等号左边调用方法都不会变化。
对象的向上转型:
      对象的向上转型,其实就是多态写法:
                格式:
                        父类名称 对象名 = new 子类名称();
                含义:
                        右侧创建一个子类对象,把它当做父类来看待使用。
      注意事项:
                        向上转型一定是安全的。从小范围转向大范围
      类似于:
                        double num = 100; //正确 int-->double,自动类型转换
      弊端:
                        对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
      解决方法:
      用对象向下转型【还原】
对象的向下转型:
      对象的向下转型,其实是一个【还原】动作
      格式:
                子类名称 对象名 = (子类名称)父类对象;
      含义:
                将父类对象,还原成为本来的子类对象。
      例如:
                Animal animal = new Cat();
                Cat cat = (Cat) animal;
      注意事项:
      1.必须保证对象创建的时候,就是猫,才能向下转型
         2.如果对象创建的时候,本来是猫,非要向下转型变成猫,就会报错。错误类型:ClassCastException

instanceof关键字:
      格式:
                对象 instanceof 类型;
                得到一个Boolean值结构,也就是判断前面的对象是否是后面类型的实例
### 案例:
```Java
public class Figure {
    double dim1;
    double dim2;

    Figure(double d1, double d2) {
      // 有参的构造方法
      this.dim1 = d1;
      this.dim2 = d2;
    }

    double area() {
      // 用于计算对象的面积
      System.out.println("父类中计算对象面积的方法,没有实际意义,需要在子类中重写。");
      return 0;
    }
}
public class Rectangle extends Figure {
    Rectangle(double d1, double d2) {
      super(d1, d2);
    }

    double area() {
      System.out.println("长方形的面积:");
      return super.dim1 * super.dim2;
    }
}
public class Triangle extends Figure {
    Triangle(double d1, double d2) {
      super(d1, d2);
    }

    double area() {
      System.out.println("三角形的面积:");
      return super.dim1 * super.dim2 / 2;
    }
}
public class Test {
    public static void main(String[] args) {
      Figure figure; // 声明Figure类的变量
      figure = new Rectangle(9, 9);
      System.out.println(figure.area());
      System.out.println("===============================");
      figure = new Triangle(6, 8);
      System.out.println(figure.area());
      System.out.println("===============================");
      figure = new Figure(10, 10);
      System.out.println(figure.area());
    }
}

执行结果:
长方形的面积:
81.0
===============================
三角形的面积:
24.0
===============================
父类中计算对象面积的方法,没有实际意义,需要在子类中重写。
0.0
```
注:
- 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
- 多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。


这篇笔记部分案例代码引用于 “C语言中文网”

ykrne 发表于 2021-7-10 23:20

不如来学 C#

LongJL 发表于 2021-7-10 23:26

ykrne 发表于 2021-7-10 23:20
不如来学 C#

{:301_977:}学不动了,

剑来…… 发表于 2021-7-11 08:05

谢谢,楼主怎么自学的

LongJL 发表于 2021-7-11 08:51

剑来…… 发表于 2021-7-11 08:05
谢谢,楼主怎么自学的

看视频,结合文档

星空下的流星 发表于 2021-7-15 11:52

留下脚印:lol

aiyao 发表于 2022-3-18 14:04

最近正在迷惑多态呢

denweiaa 发表于 2022-5-13 17:28

有没有好点的教程学习一下

janiow 发表于 2022-5-24 15:34

denweiaa 发表于 2022-5-13 17:28
有没有好点的教程学习一下

b站韩顺平的视频质量很高 很细致

YuFeng74 发表于 2022-5-24 20:04

java学到这就不想学了{:301_999:}
页: [1] 2
查看完整版本: 【自学笔记】 Java基础 - 面向对象(二)三大特征