Java入门之面向对象-划重点

Posted Jennyism丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java入门之面向对象-划重点相关的知识,希望对你有一定的参考价值。

Java入门(七)之面向对象-划重点

0. 面向对象的概念

0.1 面向对象和面向过程

  • 面向对象是一种软件开发方法,这种方法可以将现实中的事物抽象出来,让我们的编程模型化。

  • 面向过程也是一种软件开发方法,它需要我们通过具体的,流程化的方式去解决问题

  • 打个比方,我们现在要吃个饭。

    • 可能我们会自己煮,所以要先去买个菜,然后洗菜切肉淘米,煮饭炒菜煲汤,然后吃掉,洗碗。这个叫做面向过程
    • 可能我们会去饭店,我们只需要点菜,然后等东西上来,吃掉,然后就付钱走人。我们不用理会菜是从哪里买的,也不用理会饭是怎么做的,吃完不用洗碗。这个叫做面向对象
  • 再举个程序的例子吧

    • C语言就是一个典型的面向过程的语言,我们在写程序的时候,会在main函数中写上我们的主程序,可能会调用其他的函数,甚至是其他文件的函数。

      #include <stdio.h>
      
      //使用C语言生成正方形
      int main(){
          printRect(3);
      }
      
      void printRect(int size){
          for(int i = 0;i<size;i++){
              for(int j = 0;j<size;j++){
                  printf("*");
              }
              printf("
      ");
          }
      }
    • Java使用的是面向对象编程,所以我们所有的编程都围绕着类来进行。我们不能直接调用方法,而是应该先创建实例,然后再调用实例的方法。

      public class Test(){
      
          public static void main(String[] args){
              RectUtil rectUtil = new RectUtil();
              rectUtil.printRect();
          }
      }
      
      ==============下面是另一个类======================
      //一个与矩形有关的工具类
      public class RectUtil(){
          //有一个生成矩形的方法
          public void printRect(int size){
              for(int i = 0;i<size;i++){
                  for(int j = 0;j<size;j++){
                      printf("*");
                  }
                  printf("
      ");
              }
          }
      }

0.2 属性和方法

  • 在现实中,对象指的是具体某一个事物。而在程序中,我们的对象是指我们编写的系统的某一个成分。
  • 对象会包含两个内容,一个是数据,一个是动作。对象不仅能够进行操作,还能记录操作的结果。举个栗子,你会吃饭,并且吃完会变重。你的吃饭是一个动作,而体重是一个数据。
  • 众所周知,类是从对象中抽象出来的,可以说:类是对具有相同特性和行为的对象的抽象。所以,类的具体化(或者说实例化)就是对象,对象的抽象化就是类。
  • 类具有属性,我们通过属性来描述类的特性。
  • 类具有方法,我们通过方法来描述类的一些操作,我们也可以叫它函数
  • 实例化为对象,类的属性可以被赋值成为对象的数据,类的方法可以被调用成为对象的一个动作,或者说操作。
  • 类,也可以当做一种数据类型。
    • 例如:String,Date都是一个类,同时他们也可以表示字符串,时间的数据。
  • 由上面这条,我们可以明确一点,类里面的属性可以是其他的类。
    • 例如:一个电脑类,它的属性可以有CPU,显卡,显示屏,而这些同样可以抽象为类,同时它们又是电脑类的属性之一。

1. 面向对象的特征

1.1 对象唯一

  • 每一个对象,都是唯一的,会有一个唯一的标识,就像C语言中的指针,存储着变量的地址,类实例化成对象后,会有一个唯一的地址存放对象。

1.2 抽象性

  • 指的就是将具有相同特性和行为的对象抽象成类。

1.3 三大特性——继承、封装、多态

1.3.1 继承

  • 继承指的是从已经存在的类中继承到它的属性和方法,这样可以减少代码的重复。
  • 父类:指的是被继承的那个类
  • 子类:指的是继承父类的类。
  • 在Java中,所有的类继承与Object,即所有类的父类都为Object
  • 在Java中,只允许被一个类继承,目的是降低多继承带来的耦合度过高
    • 我们可以通过多个接口,拓展类的功能。

1.3.2 封装

  • 生活中的封装指的是将东西包裹起来

    • 例如电脑机箱将内部的元件封装,我们看到的是机箱,可以使用开机按钮,而看不到内部的元件。
  • 在程序设计中,我们可以将类封装起来,只提供需要的方法接口,而不需要提供具体的实现细节。

    • 例如:我们实现一个翻译单词的类,我们需要做几件事
      1. 写一个读取单词列表的方法
      2. 写一个在单词列表中查找我们要翻译单词的方法
      3. 写一个方法整合上面两个方法,实现业务逻辑:读取单词列表 -> 查找目标 -> 返回结果
    • 而在这之中,我们只需要第三个方法就可以实现翻译单词。而另外两个方法可以不暴露出来,从而让我们代码更加健壮。
  • 封装有四个修饰符

    范围/修饰符 类的内部 包的内部 任何位置 适用 备注
    public 修饰类,成员属性,成员方法,内部类
    protected 修饰成员属性,成员方法,内部类 不能修饰类
    默认不写 修饰类,成员属性,成员方法,内部类
    private 修饰成员属性,成员方法,内部类 私有方法不能被继承
  • 封装的原则

    • 把不需要对外提供的内容都隐藏起来,把属性都隐藏起来,提供公共方法对其访问(通常使用get获取,set设置)
  • 封装的结果是存在,但是不可见

1.3.3 多态

  • 同名的不同方法

  • 将子类对象赋值给父类变量,调用的方法为子类的方法。由此,同个类型的对象在执行同一个方法时,可以表现出多种行为特征

    • 例子:QQ群中的管理员和群成员。管理员也是群成员,所以可以说群成员是管理员的子类。
    • 当我在使用修改备注功能的时候,群成员只能修改自己的备注,而管理员可以修改其他人的备注。
    • 同理,群主也继承于群成员,但是群主有更多的权限。
  • 此时,如果你想调用父类的方法,可以使用super关键字。

  • 父类中声明为static、final的方法不能被覆盖,而且声明为final的类的所有方法不允许被覆盖。

  • 方法的重载

    • 方法的重载是另一种实现多态的方法,它指的是在类中,定义同名的方法,但是这些方法具有不同的参数类型,参数个数,则可以实现多态。
    • 使用这种方法时,当我们填入的数据类型为对应方法的类型时,就会调用该方法。
    test(int i){}
    test(String str){}
    test(int i,String str){}
    当我调用test(1)时,会自动的调用到第一个方法,而调用test("1")时,会自动调用到第二个方法。

2. 继承相关

2.1 抽象类

  • 抽象类使用abstract class关键字来定义
  • 抽象类除了不能实例化外,写法与普通类并无二致
  • 由于不能实例化,抽象类只有被继承才能使用,因此一般在设计时就会决定是否使用抽象类
public abstract class AStudent{
    private String id;
    private String name;
    private String dept;
    
    public void study(){
        System.out.println("我在学习!");
    }
}

public class GoodStudent extends AStudent{
    public void study(){
        super().study();
        System.out.println("敲代码,进大厂!");
    }
}

public class BadStudent extends AStudent{
    public void study(){
        System.out.println("什么时候可以下课,我要去食堂抢位置了!");
    }
}

2.2 接口

  • 接口使用interface关键字来声明

  • 接口不是类,类包含属性和方法,而接口包含要实现的类
  • 接口无法被实例化,只能被实现
  • 实现
    • 接口中的方法是没有实现的,即只有方法名,没有方法的内容。
    • 我们可以理解为,这是一个空白的田字格,告诉顶上写拼音,下边写汉字,但是写什么拼音,什么汉字可以由你自己定。
public interface Teacher [extends 这里可以继承其他接口,但是我不做示范]{
    public void teaching([这里可以写变量,但是我不做示范]);
}

public class TeacherImpl implements Teacher{
    //如果你实现了接口,那么类中必须有接口里所有的方法的实现
    public void teaching(){
        [代码内容]
    }
}

3. 多态相关

3.1 构造方法

  • 构造方法是类的一种特殊方法,用来初始化新的对象。
    • 当我们实例化时,会写:new Student()这种写法,这里的Student为什么会有括号,因为调用了构造方法。
  • 当我们不写构造方法时,会有默认的一个无参的构造方法(无参指的是没参数)
  • 当我们写一个构造方法时,无参的构造方法会被覆盖,即此时没有默认的构造方法
    • 因此,当我们写一个有参的构造方法时,如果还想不调用构造方法,可以再写一个空白的无参构造方法
public class test{
    //构造方法与类名同名,不用定义返回值,我们可以认为返回值为这个类。
    public test(){
        
    }
    //有参的构造方法
    public test(int i){
        
    }
}
  • 由多态的性质,我们可以知道,构造方法可以有很多个,因为它本身也是一个方法,符合多态的特性。

  • 跟普通方法不同的是,它是在类被实例化的时候调用的。

    • 在没有自己写构造方法时,会默认一个无参的构造方法
    • 在写了一个构造方法时,没有默认的无参构造方法。
  • 我们可以将其应用在,需要给多个属性赋值的时候。

    • //如果没有构造方法
      Student student = new Student();
      student.id = "123456";
      student.name = "小明";
      //如果有构造方法
      Student student = new Student("123456","小明");
      student = new Student();//如果没有写无参的构造方法,此时这样写会报错

课后习题

  • 尝试使用面向对象的思想进行编程,讲述一个小故事

  • 例如:

    恋爱的狮子与农夫 

    ? 狮子爱上了农夫的女儿,请求农夫把女儿嫁给他。农夫既不忍心把女儿许配给野兽,又不敢拒绝,就想出一个办法
      
      当狮子来催促的时候,农夫对他说:“我愿意把女儿嫁给你,可是我的女儿害怕你的尖牙和利爪,而且我也担心这些会伤害到她。如果你能剪掉你的利爪,并且磨平你的牙齿,我就立刻让女儿与你成婚。”
      
      狮子高兴得不得了,说道:“只要能娶到她,什么条件我都答应,我马上按照你的意思去做!”
      
      狮子回去后剪掉了自己尖利的爪子,在磨石上磨平了尖锐的牙齿。他打扮一新,到农夫家里迎娶新娘。可是到了农夫家门口,却发现农夫手提木棒,朝自己走来,看样子来者不善。狮子警惕地摆好了架势。
      
      果然农夫一阵乱棒像雨点一样敲击下来,但是狮子却无力还击,因为他的爪子和牙齿全然没有任何威力。
      
      最后狮子落荒而逃,更糟糕的是,没有了尖牙、利爪,狮子再也无法捕捉到猎物,最后饿得奄奄一息。

角色类

package domain;

/**
 * @author Jennyism
 * @date 2020/1/27 0027 21:47
 */
public abstract class Role {
    private String name;

    public void say(String words) {
        System.out.println(getName() + ":" + words);
    }

    public void think(String feel) {
        System.out.println(getName() + "觉得" + feel);
    }

    public void attack(Role role) {
        System.out.println(getName() + "对" + role.getName() + "发起攻击");
    }

    public void doSomething(String some) {
        System.out.println(getName() + some);
    }

    public String getName() {
        return name;
    }

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

狮子类

package domain;

/**
 * @author Jennyism
 * @date 2020/1/27 0027 21:52
 */
public class Lion extends Role {
    private boolean claw;
    private boolean canineTeeth;

    public Lion(String roleName) {
        setName(roleName);
        System.out.println("我是一只狮子,我的名字叫" + getName() + ",我爱上了农夫的女儿");
    }

    public void wantMarry(Role role) {
        System.out.println(getName() + "想娶" + role.getName());
    }



    public boolean hasClaw() {
        return claw;
    }

    public void setClaw(boolean claw) {
        if (!claw){
            System.out.println(getName()+"剪掉了自己尖利的爪子!");
        }
        this.claw = claw;
    }

    public boolean hasCanineTeeth() {
        return canineTeeth;
    }

    public void setCanineTeeth(boolean canineTeeth) {
        if (!claw){
            System.out.println(getName()+"在磨石上磨平了尖锐的牙齿。");
        }
        this.canineTeeth = canineTeeth;
    }
}

农夫类

package domain;

/**
 * @author Jennyism
 * @date 2020/1/27 0027 22:01
 */
public class Farmer extends Role {
    public Farmer(String roleName){
        setName(roleName);
        System.out.println("我是农夫,我的名字叫"+getName()+",狮子要娶我的女儿,可我不敢拒绝。");
        System.out.println("于是我想到了一个办法。");
    }
}

女儿类

package domain;

/**
 * @author Jennyism
 * @date 2020/1/27 0027 22:06
 */
public class Daughter extends Role {
    public Daughter(String roleName){
        setName(roleName);
    }
}

故事讲述

package client;

import domain.Daughter;
import domain.Farmer;
import domain.Lion;
import domain.Role;

/**
 * @author Administrator
 */
public class MyFirstClient {

    public static void main(String[] args) {
        //狮子有自己的方法,需要赋值到Lion类
        Lion lion = new Lion("Lion Steve");
        //女儿没有再添加新的方法,可以直接赋值给Role类
        Role daughter = new Daughter("Daughter Fuck");
        lion.wantMarry(daughter);
        lion.say("农夫,你能把你的女儿嫁给我吗。");
        Role farmer = new Farmer("Farmer Fuck");
        System.out.println("=============第一段结束==========");
        lion.say("农夫,你要怎样才能把女儿嫁给我!");
        farmer.say("我愿意把女儿嫁给你,可是我的女儿害怕你的尖牙和利爪,而且我也担心这些会伤害到她。如果你能剪掉你的利爪,并且磨平你的牙齿,我就立刻让女儿与你成婚。");
        lion.think("高兴极了");
        lion.say("只要能娶到她,什么条件我都答应,我马上按照你的意思去做!");
        System.out.println("=============第二段结束==========");
        lion.setClaw(false);
        lion.setCanineTeeth(false);
        lion.doSomething("打扮一新,前去迎娶新娘");
        farmer.doSomething("提着木棒走来!");
        farmer.attack(lion);
        lion.attack(farmer);
        lion.doSomething("落败逃走,没有了尖牙、利爪,狮子再也无法捕捉到猎物,最后饿得奄奄一息。");
        System.out.println("=============全剧终==========");
    }
}

以上是关于Java入门之面向对象-划重点的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE入门学习21:Java面向对象之接口(interface)

零基础快速入门Java的秘诀

Java中面向对象的三大特性之封装

JavaSE入门学习15:Java面向对象之继承

Scala入门系列:面向对象之继承

Scala入门系列:面向对象之object