Is it okay for a class to have a field of its own

2019-02-23 08:48发布

问题:

I did the following, i got a stackoverflow error after some time, and I understand why it was.

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.

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. 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). So technically I cannot test this class.

So my question is WHY does java allow to create an instance variable of its own type? 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. 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?

回答1:

Classes like this exist all the time.

Consider linked lists or trees, e.g.,

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. 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, e.g., you'd add them via a method and not in a constructor.



回答2:

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
 }


回答3:

There can be multiple constructors. Thus, you can have another constructor

public Cat(){...}

That would allow you to create an inside Cat. Afterwards you could create another Cat that contains the inside 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.



回答4:

There are many examples of self referencing data structures that are valid. Think of a LinkedList. Each LinkNode has a data field, and a pointer to the next 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.

Just think of your Cat example. Why would instantiating a Cat require of all things...another Cat!



标签: java oop object