我终于明白了什么是类 Chris 类 Daniel 类 我们得到了什么好处?结语 额外提示

2025-05-25

我终于明白了什么是阶级

克里斯班

丹尼尔班

我们得到了什么好处?

最后的话

额外提示

有一句话是这么说的:

“每个脑袋都是一个完全不同的世界。”

我认为确实如此true。有些人可能会说某个老师不懂事,但也许是因为他/她的教学方式与你的大脑“连接方式”不相容。我想这本身就是一种没有对错之分的事情。

许多事情都有不同的解读,这可能会导致宝贵信息的丢失。

所以,今天我想解释一下我是如何class理解 a 这个概念的。不仅仅是概念上的,还要解释为什么它们在我们的代码中很有用:

当我们开始编程时,我们首先学习的东西之一就是变量常量

因此,如果我们的任务是在控制台上打印你的nameageheight你可能会做这样的事情:

注意:我决定不使用class类似的方式Scanner来请求用户输入,以使其尽可能简单。

// Java

public class Main {
    public static void main(String[] args) {
        String name = "Chris";
        int age = 23;
        double height = 1.85;
        System.out.println("name: " + name + ", age: " + age + ", height: " + height);
    }
}
Enter fullscreen mode Exit fullscreen mode

这将输出:

name: Chris, age: 23, height: 1.85
Enter fullscreen mode Exit fullscreen mode

伟大的!

但是,现在我们想让变量名更具描述性,添加一个“chris”前缀怎么样?看看吧:

// Java

public class Main {
    public static void main(String[] args) {
        String chrisName = "Chris";
        int chrisAge = 23;
        double chrisHeight = 1.85;
        System.out.println("chrisName: " + chrisName + ", chrisAge: " + age + ", chrisHeight: " + chrisHeight);
    }
}
Enter fullscreen mode Exit fullscreen mode

好的!

现在,让我们添加另一个人的信息:

// Java

public class Main {
    public static void main(String[] args) {
        String chrisName = "Chris";
        int chrisAge = 23;
        double chrisHeight = 1.85;
        System.out.println("chrisName: " + chrisName + ", chrisAge: " + age + ", chrisHeight: " + chrisHeight);

        String danielName = "Daniel";
        int danielAge = 27;
        double danielHeight = 1.71;
        System.out.println("danielName: " + danielName + ", danielAge:" + danielAge + ", danielHeight:" + danielHeight)
    }
}
Enter fullscreen mode Exit fullscreen mode

嗯...🤔

你开始看出某种模式了吗?

我们存储了来自两个不同人的相同 3 个值...

这时就需要class救援了!

超人正在路上

person让我们一步一步地重构我们的代码,每次只关注一个。

克里斯班

在面向对象编程 (OOP) 中,对象classes被设计为以高内聚性来表示状态行为。简而言之:这意味着给定对象的变量和方法是相互关联的。如果某个方法不使用对象中的任何变量,则可能表明它不属于它所属的位置。classclass

现在我们有了这个想法,我们可以创建一个具有默认构造函数class的Chris,它将采用chrisNamechrisAgechrisHeight

Aconstructor是一种特殊的函数,它必须与它所属的 具有相同的名称class+ 没有返回值(甚至不需要void关键字),通常用于确保 的实例class位于 中valid state

Valid state表示object具有预期的值。

Anobject是 a 的具体实现class(我们稍后会看到它的实际作用)。

所以,我们的克里斯class看起来是这样的:

// Java

public class Chris {
    private String name;
    private int age;
    private double height;

    public Chris(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}
Enter fullscreen mode Exit fullscreen mode

关键字this用于指代我们的全局范围,class以便将name的参数constructor与实际的全局范围的区分开来name

现在我们可以重构我们的代码以便使用我们全新而闪亮的 Chris class

因此,不要:

String chrisName = "Chris";
int chrisAge = 23;
double chrisHeight = 1.85;
Enter fullscreen mode Exit fullscreen mode

我们可以有:

Chris chris = new Chris("Chris", 23, 1.85);
Enter fullscreen mode Exit fullscreen mode

该关键字new用于指代constructor我们的 Chris class

并且chris(注意小写“c”)就是我们所说的object,因为它是我们的 Chris 的具体或“真实”实现class

但由于我们不再有chrisName我们的代码将无法正确编译。chrisAgechrisHeight

有趣的...

我们怎样才能解决这个问题?

好吧,如果我们回到 Chris 的class实现,我们可以看到我们的全局作用域变量(也称为fieldsprivate fieldsmember variables)是private。因此,我们无法从外部访问它们。

为了能够做到这一点,我们必须添加public可以帮助我们访问该数据的方法。

// Java

public class Chris {
    private String name;
    private int age;
    private double height;

    public Chris(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public double getHeight() {
        return height;
    }
}
Enter fullscreen mode Exit fullscreen mode

你注意到 get...() 方法没有使用this关键字吗?这是因为没有与它们的名称匹配的参数,所以编译器知道我们引用的是全局作用域的变量。

现在我们有了这些方法,我们可以使用(.)运算符来访问它们,如下所示:

// Java

public class Main {
    public static void main(String[] args) {
        Chris chris = new Chris("Chris", 23, 1.85);
        System.out.println("chrisName: " + chris.getName() + ", chrisAge: " + chris.getAge() + ", chrisHeight: " + chris.getHeight());

        String danielName = "Daniel";
        int danielAge = 27;
        double danielHeight = 1.71;

        System.out.println("danielName: " + danielName + ", danielAge:" + danielAge + ", danielHeight:" + danielHeight)
    }
}
Enter fullscreen mode Exit fullscreen mode

那就更好了!

不,等等...

现在我们要为 Daniel 做同样的事情,让我们创建一个 Daniel class

丹尼尔班

// Java

public class Daniel {
    private String name;
    private int age;
    private double height;

    public Daniel(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public double getHeight() {
        return height;
    }
}
Enter fullscreen mode Exit fullscreen mode

现在我们的主要内容class是:

// Java

public class Main {
    public static void main(String[] args) {
        Chris chris = new Chris("Chris", 23, 1.85);
        System.out.println("chrisName: " + chris.getName() + ", chrisAge: " + chris.getAge() + ", chrisHeight: " + chris.getHeight());

        Daniel daniel = new Daniel("Daniel", 27, 1.71);
        System.out.println("danielName: " + daniel.getName() + ", danielAge:" + daniel.getAge() + ", danielHeight:" + daniel.getHeight())
    }
}
Enter fullscreen mode Exit fullscreen mode

好的!

现在我们的 Mainclass比以前更短了。

但我们还有一件事要做……

如果你认真想想,我们基本上在 Chris 和 Daniel 内部执行的是相同的逻辑classes🤔。

这意味着我们没有针对这个特定情况使用正确的抽象。为了找到解决方案,我们需要知道 Chris 和 Daniel 是什么……

没错!他们都是Person

因此,如果我们删除 Danielclass并将 Chris 重命名class为“Person”,我们的代码最终将变成:

// Java

public class Main {
    public static void main(String[] args) {
        Person chris = new Person("Chris", 23, 1.85);
        System.out.println("chrisName: " + chris.getName() + ", chrisAge: " + chris.getAge() + ", chrisHeight: " + chris.getHeight());

        Person daniel = new Person("Daniel", 27, 1.71);
        System.out.println("danielName: " + daniel.getName() + ", danielAge:" + daniel.getAge() + ", danielHeight:" + daniel.getHeight())
    }
}
Enter fullscreen mode Exit fullscreen mode

我们得到了什么好处?

  • 我们的代码现在更短了,但并没有失去它的含义。
  • 我们将需要的 2 个新项目减少classes到 1 个。
  • 我们减少了在更多需要的地方重复“Chris”和“Daniel”的噪音。
  • 我们设法在单个中重复使用我们的逻辑class
  • 现在我们可以很快知道和都是chrisdaniel一个类的具体实现,或者我喜欢称它们为:兄弟。
  • 现在我们甚至可以在其他项目中使用这个 Person class,它仍然可以正常工作。

最后的话

我希望这个例子能帮助您,先生/女士,理清您对类是什么以及为什么我们在面向对象编程中使用它们的想法:)

下篇文章再见!

额外提示

这一条来自下面的@alphashuroPerson的评论:另一个好处是,现在我们可以通过创建一个接受对象的函数来替换代码中打印 a 信息的部分Person,如下所示:

// Java

public class Main {
    public static void main(String[] args) {
        Person chris = new Person("Chris", 23, 1.85);
        printPersonalInfo(chris);

        Person daniel = new Person("Daniel", 27, 1.71);
        printPersonalInfo(daniel);
    }

    public static void printPersonalInfo(Person person) {
        System.out.println("name: " + person.getName() + ", age:" + person.getAge() + ", height:" + person.getHeight());
    }
}
Enter fullscreen mode Exit fullscreen mode

通过这个“小”改动,我们获得了无需维护两行不同代码的好处。如果我们需要以不同的方式呈现某人的信息,代码中只需要修改一处即可。

感谢 Alpha 提出这个问题。

现在,我要对我们的代码进行另一项调整。

由于该printPersonalInfo()函数只接受Person对象,这意味着该方法直接依赖于该类Person。也就是说,它实际上应该是该类的一部分!

因此,让我们继续将函数移动到Person类中,而不是让它在我们的类中徘徊Main

// Java

public class Person {
    private String name;
    private int age;
    private double height;

    public Person(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    // Imagine we still have the getters here :P
    // this is just to make the code block shorter.

    public void printInfo() {
        System.out.println("name: " + name + ", age:" + age + ", height:" + height);
    }
}
Enter fullscreen mode Exit fullscreen mode

现在,您可能已经注意到我必须做一些调整:

  • 删除该person参数。
  • 将每个 Getter 方法调用替换为全局变量。
  • 将方法从“printPersonalInfo()”重命名为“printInfo()”。

最后一点可以是可选的,也可以是个人偏好。我个人觉得名称中的“Personal”部分有点多余,因为我们知道Person稍后会创建一个对象。

好的,现在我们还必须Main根据这个新实现对我们的课程做一些调整:

// Java

public class Main {
    public static void main(String[] args) {
        Person chris = new Person("Chris", 23, 1.85);
        chris.printInfo();

        Person daniel = new Person("Daniel", 27, 1.71);
        daniel.printInfo();
    }
}
Enter fullscreen mode Exit fullscreen mode

如果你稍微想一想,我们甚至不需要 Getter 方法,这种做事方式与 OOP 的原则之一“封装”相关,这是另一篇文章的主题😉。

🎊 如果你读完整个内容,还能获得额外积分!🎉

文章来源:https://dev.to/chrisvasqm/how-i-finally-understood-what-a-class-is--24pl
PREV
编码概念 - 泛型 什么是泛型?为什么要使用泛型? 附加阅读
NEXT
JavaScript 的未来——值得关注的功能