Java基础(七)—— 类与对象

7.1 用类制造对象

  • 之前理解了对象变量和普通变量的不同,对象变量是对象的管理者而非所有者,所以涉及到赋值、函数参数传递和比较都与普通变量有所不同。
  • 现在,我们要来尝试自己定义类,然后用自己定义的类来创建对象。
  • 类和对象的关系:类定义了对象长什么样,对象则是按照类的定义所制造出来的实体,一个类可以创建很多对象,每个对象有自己的数据。
  • 对象是实体,需要被创建,可以为我们做事情

7.2 定义类

  • 一个类由两种东西组成:表示对象有什么的成员变量和表示对象能做什么的成员函数。
  • 一旦定义了类,我们就可以创建这个类的多个对象,这些对象都会做那个类所定义的动作(函数),但是各自具有不同的数据。
  • 例子:自动售卖机
package com.meteor.vendingmachine;

public class VendingMachine {

    int price = 80;

    int balance;

    int total;

    void showPrompt() {
        System.out.println("Welcome");
    }

    void insertMoney(int amount) {
        balance = balance + amount;
    }

    void showBalance() {
        System.out.println(balance);
    }

    void getFood() {
        if (balance >= price) {
            System.out.println("Here you are.");
            balance = balance - price;
            total = total + price;
        }
    }

    public static void main(String[] args) {
        VendingMachine vm = new VendingMachine();
        vm.showPrompt();
        vm.showBalance();
        vm.insertMoney(100);
        vm.getFood();
        vm.showBalance();
    }
}

7.3 成员变量和成员函数

  • 类定义了对象中所具有的变量,这些变量称作成员变
  • 每个对象有自己的变量,和同一个类的其他对象是分开的
  • 在函数中可以直接写成员变量的名字来访问成员变量
  • 函数是通过对象调用的
  • this是成员函数的一个特殊的固有的本地变量,它表达了调用这个函数的那个对象
void setPrice(int price) {
    this.price = price;
}
  • 通过.运算符调用某个对象的函数
  • 在成员函数内部直接调用自己(this)的其他函数
    void insertMoney(int amount) {
        balance = balance + amount;
        showBalance();
    }
  • 定义在函数内部的变量是本地变量
  • 本地变量的生存期和作用域都是函数内部
  • 成员变量的生存期是对象的生存期,作用域是类内部的成员函数

7.4 对象初始化

  • 变量的初始化是程序安全很重要的一环。一旦创建了一个对象,有什么手段可以保证其中的每一个成员变量都有确定的初始值呢?
  • 成员变量在定义的地方就可以给出初始值
    • 对象变量的0值表示没有管理任何对象,也可以主动给null值
  • 定义初始化可以调用函数,甚至可以使用已经定义的成员变量

构造函数

  • 如果有一个成员函数的名字和类的名字完全相同,则在创建这个类的每一个对象的时候会自动调用这个函数一>构造函数
  • 这个函数不能有返回类型
public class VendingMachine {

    int price = 80;

    int balance;

    int total;

    VendingMachine() {
        total = 20;
    }

    VendingMachine(int price) {
        this.price = price;
    }
}

函数重载

  • 一个类可以有多个构造函数,只要它们的参数表不同
  • 创建对象的时候给出不同的参数值,就会自动调用不同的构造函数
  • 通过this()还可以调用其他构造函数
  • 一个类里的同名但参数表不同的函数构成了重载关系

7.5 对象交互

  • 面向对象程序设计的第一步,就是在问题领域中识别出有效的对象,然后从识别出的对象中抽象出类来。面对纷繁复杂的现实问题,往往存在多种对象划分的方式,而不同的划分会带来类的设计以至于程序结构的各种不同。我们举了一个数字钟的例子,希望通过这个例子表明对象划分的重要性,给你一个感性认识。在今后面对实际的问题领域时,可以试试用这里提到的概念来做对象的划分和类的设计。但是这只是一个例子,遇到具体情况一定是具体分析,按照问题领域的实际情况来做。
  • 一个对象当然可以由其他类的对象来组成,就像一个人体里面有心脏、肠胃一样。对象是由其他对象组成的,而类定义了这样的组合关系。
    那么下一个问题,就是当一个对象里有多个对象的时候,那些对象之间是如何交互的,对象和对象之间的联系是如何建立的,对象如何和其他对象交流。对象和对象之间的联系紧密程度叫做耦合。对象和对象的耦合程度越紧,表现在源代码上,就是它们的代码是互相依赖、互相牵制的。我们理想的模型,是对象和对象之间的耦合要尽可能的松,平行的对象要尽量减少直接联系,让更高层次的对象来提供通信服务。这些就是在我们这个非常简单的数字钟的例子中所体现的。
    要实现一个数字钟非常简单,如果只是实现功能,一个循环就可以了。这里所体现的,是更深层次的面向对象设计的理念。

对象的识别

  • 数字时钟,可以看成是两个两位的显示器,表示小时的从00到23,表示分钟的从00到59,他们有相同的东西,也有不同的东西
package com.meteor.object.clock;

public class Display {

    private int value;

    private int limit;

    Display(int limit) {
        this.limit = limit;
    }

    public void increase() {
        value++;
        if (value == limit) {
            value = 0;
        }
    }

    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        Display d = new Display(24);
        for (;;) {
            d.increase();
            System.out.println(d.getValue());
        }
    }
}

对象的交互

  • 实现了单个显示器的显示,要做数字时钟,需要一个hour和一个minute,这两个变量都应该是Display类型的。
  • 一个类中,成员变量可以是其他类的对象,一个对象可以是由其他对象组成的
package com.meteor.object.clock;

public class Clock {

    private Display hour = new Display(24);

    private Display minute = new Display(60);

    public void start() {
        while(true) {
            minute.increase();
            if (minute.getValue() == 0) {
                hour.increase();
            }
            System.out.printf("%02d:%02d\n",hour.getValue(),minute.getValue());
        }

    }

    public static void main(String[] args) {
        Clock clock = new Clock();
        clock.start();
    }
}

7.6 访问属性

  • 封装,就是把数据和对这些数据的操作放在一起,并且用这些操作把数据掩盖起来,是面向对象的基本概念之一,也是最核心的概念。我们有一个非常直截了当的手段来保证在类的设计的时候做到封装:
    • 所有的成员变量必须是private的,这样就避免别人任意使用你的内部数据;
    • 所有public的函数,只是用来实现这个类的对象或类自己要提供的服务的,而不是用来直接访问数据的。除非对数据的访问就是这个类及对象的服务。简单地说,给每个成员变量提供一对用于读写的get/set函数也是不合适的设计。

封闭的访问属性

  • private只有这个类内部可以访问,类内部指类的成员函数和定义初始化。这个限制是对类的而不是对对象的

开放的访问属性

  • public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用

7.7 包

  • 当你的程序越来越大的时候,你就会需要有一个机制帮助你管理一个工程中众多的类了。包就是Java的类库管理机制,它借助文件系统的目录来管理类库,一个包就是一个目录,一个包内的所有的类必须放在一个目录下,那个目录的名字必须是包的名字。
  • Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等
  • 包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。
  • 如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。
  • 为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用 “import” 语句可完成此功能。
  • 在 java 源文件中 import 语句应位于 package 语句之后

7.8 类变量与类函数

  • 类是描述,对象是实体。在类里所描述的成员变量,是位于这个类的每一个对象中的。
  • 而如果某个成员有static关键字做修饰,它就不再属于每一个对象,而是属于整个类的了。
  • 通过每个对象都可以访问到这些类变量和类函数,但是也可以通过类的名字来访问它们。类函数由于不属于任何对象,因此也没有办法建立与调用它们的对象的关系,就不能访问任何非static的成员变量和成员函数了。

类变量

  • private static int step = 1;
Display d = new Display(24);
Display d1 = new Display(10);
System.out.println(d.step);//1
System.out.println(d1.step);//1
d.step = 2;
System.out.println(d.step);//2
System.out.println(d1.step);//2
Display.step = 3;
System.out.println(d.step);//3
System.out.println(d1.step);//3

类函数

  • static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
  • 但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的

猜你喜欢

转载自blog.csdn.net/u011741311/article/details/79182465
今日推荐