简体   繁体   English

一个类可以拥有自己类型的字段吗?

[英]Is it okay for a class to have a field of its own type

I did the following, i got a stackoverflow error after some time, and I understand why it was. 我做了以下,一段时间后我得到了stackoverflow错误,我明白为什么会这样。

public class Cat {
    String name="default name";
    Cat insideCat;

    public Cat(){
         System.out.println("Cat constructor");
         insideCat = new Cat();
    }

}

But what if I don't create a new Cat object within the constructor, but take a parameter of Cat type and assign it to the insideCat field. 但是如果我不在构造函数中创建一个新的Cat对象,但是获取Cat类型的参数并将其分配给insideCat字段。

public class Cat {
    String name="default name";
    Cat insideCat;

    public Cat(Cat insideCat){
         System.out.println("Cat constructor");
         this.insideCat = insideCat;
    }

}

I am just playing around with the code, just trying to find out what Java can do and cannot. 我只是在玩代码,只是试图找出Java可以做什么,不能做什么。 In the second code, everything looked normal, until I started to test this class. 在第二个代码中,一切看起来都很正常,直到我开始测试这个类。 I need a Cat object to create a Cat object (and to create this Cat object I need another Cat object...and it goes on). 我需要一个Cat对象来创建一个Cat对象(并创建这个Cat对象,我需要另一个Cat对象......然后它继续)。 So technically I cannot test this class. 所以从技术上讲,我无法测试这门课程。

So my question is WHY does java allow to create an instance variable of its own type? 所以我的问题是为什么java允许创建自己类型的实例变量? I guess the whole purpose of a constructor is to initialize it's instance variables. 我想构造函数的整个目的是初始化它的实例变量。 So either I have to create a new object to initialize the insideCat or else I have to take Cat object from outside. 所以要么我必须创建一个新对象来初始化insideCat,否则我必须从外面获取Cat对象。 Both doesn't seem to work. 两者似乎都不起作用。

What am I missing here. 我在这里想念的是什么 Is there any occurrence where instance variables of its own types can become useful, and can be used without any problem? 是否存在其自身类型的实例变量可以变得有用的情况,并且可以毫无问题地使用? Is it bad OOP practice to come up with classes like this? 想出这样的课程是不是OOP练习不好?

Classes like this exist all the time. 像这样的类一直存在。

Consider linked lists or trees, eg, 考虑链接列表或树,例如,

class ListNode {
  ListNode next;
  // Etc.
}

class TreeNode {
  TreeNode left;
  TreeNode right;
  // Etc.
}

You wouldn't initialize the "child" objects in the constructor, you'd add them later. 您不会在构造函数中初始化“子”对象,稍后您将添加它们。

In your example you'd need to have a method that created the insideCat at a later time. 在您的示例中,您需要一个稍后创建insideCat的方法。 In general you wouldn't create child objects that had the exact same state, there'd be something to differentiate them either at construction time, in which case you could have a "oh god stop creating these now" condition, or while they were being added, eg, you'd add them via a method and not in a constructor. 一般来说,你不会创建具有完全相同状态的子对象,在构造时有一些东西可以区分它们,在这种情况下你可以有一个“哦,上帝停止创建这些现在”的条件,或者它们是添加,例如,您将通过方法而不是在构造函数中添加它们。

There is nothing wrong in having an instance member of same class. 拥有相同类的实例成员没有任何问题。 an Employee has a manager and the manager is also an Employee 员工有经理,经理也是员工

 public class Employee{
     private Employee manager;
     //getters setters and constructor
 }

There are many examples of self referencing data structures that are valid. 有许多自引用数据结构的例子是有效的。 Think of a LinkedList . 想想LinkedList Each LinkNode has a data field, and a pointer to the next LinkNode . 每个LinkNode都有一个数据字段和一个指向下一个LinkNode的指针。

class LinkNode {
    int data;
    LinkNode nextLink;

    public LinkNode(int d1) {
        data = d1;
        nextLink = null;
    }
    ...
}

class LinkedList {
    private LinkNode first;
...
}

Your StackOverflow problem stems from the fact that creating an instead of X requires the creation of another X , ad-infinitum. 您的StackOverflow问题源于这样一个事实:创建一个而不是X需要创建另一个X ,无限广告。

Just think of your Cat example. 想想你的Cat例子。 Why would instantiating a Cat require of all things...another Cat ! 为什么实例化猫需要所有东西......另一Cat

There can be multiple constructors. 可以有多个构造函数。 Thus, you can have another constructor 因此,您可以拥有另一个构造函数

public Cat(){...}

That would allow you to create an inside Cat. 这将允许您创建内部Cat。 Afterwards you could create another Cat that contains the inside Cat. 然后你可以创建另一个包含内部Cat的Cat。 Obviously, the design might not be great here, depending on your needs. 显然,根据您的需要,这里的设计可能不太好。 Dave Newton's answer about linked list is a great real world example of this usage. Dave Newton关于链表的答案是这种用法的一个很好的现实世界的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM