0

I'm new to java and am running into the error

An enclosing instance that contains ... is required

when creating a new object from a subclass defined in the same source file as its parent, but not when the subclass has its own source file, and I'd like to understand why.

The main file:

package tessty
public class Tessty {
    public static void main(String[] args) {
        Person me = new Person();
        me.addtoitems();
    }
}

Another source file for the "Person" class:

package tessty;
import tessty.Item.*; // I included this import as per NetBeans' suggestions

public class Person {

    Item[] items;

    public Person() {
        items = new Item[3];
    }

    public void addtoitems() {
        items[0] = new Apple(); // Compile error thrown here
        items[1] = new Shoe(); // and here
        items[2] = new Hat(); // but not here
    }
}

The "Item" class source file with two sub-classes defined in the same file:

package tessty;

public class Item {

    int weight;

    public class Apple extends Item {
        public Apple() {
            weight = 2;
        }
    }

    public class Shoe extends Item {
        public Shoe() {
            weight = 3;
        }
    }

}

And finally, another child of Item, but defined in its own source file:

package tessty;

public class Hat extends Item {

    public Hat() {
        weight = 1;        
    }

}

I'd really like to be able to define sub-classes in the same file as the parent class for organizational purposes (the application I'm working on will have many "small" sub-classes). Could someone please explain why I'm getting this error only for the sub-classes that are in the same source file as their parents? Is it related to the fact I have to use an import for the sub-classes in the same file as their parent and not for the sub-class with its own file?

durron597
  • 31,968
  • 17
  • 99
  • 158
Lain2
  • 33
  • 4
  • `Apple` and `Shoe` need to be declared `static` to work the way you are trying. – FatalError Jan 14 '15 at 15:58
  • Thanks all, using the static modifier does indeed remove the error. I didn't realize defining a subclass in the same source file makes it an "inner" class, so I'm going to go read up on those. – Lain2 Jan 14 '15 at 16:04
  • I took the liberty of re-titling your question to better reflect your question and remove any suggestion this was opinion-based, and also to remove the tag from the title (future tip: don't put tags in titles). – Andy Brown Jan 14 '15 at 16:27

2 Answers2

5

First, your Testty class doesn't compile. You've missed a ; after the package statement:

package tessty;

Then, you can define super and subclass in one source file, but one of them has to be public and you need the package statement just once (because it's shared for both of the classes). For example:

package something;

public class SuperClass {

}

class SubClass extends SuperClass {

}

The source-file they will be stored, will have to be named SuperClass.java.

Alternatively, you can make the sub-class(es) nested and static, as answered by @AndyBrown.

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • 1
    There's one case you missed, when you declare SubClass `public static` – ControlAltDel Jan 14 '15 at 15:57
  • @ControlAltDel I believe that would be when you put `SubClass` inside of `SuperClass`, right? – Nic Jan 14 '15 at 15:57
  • No, in the snippet I've provided, if `SubClass` is `static` (no matter `public` or not), it doesn't compile. – Konstantin Yovkov Jan 14 '15 at 15:58
  • Yes, the static modifier could make sense if SubClass were defined as an inner class relative to SuperClass, but since that is not the case here, it's good. Even for an inner class, there is no requirement for it to be declared as static, however. – unigeek Jan 14 '15 at 16:01
2

You need to make your subclasses static member classes for this to work. As it is they are inner classes, but there is no point in using those in your case. You could also make Item abstract as you don't intend to create any instance of it.

If you were to create non-nested classes in a single file, only one can be public (as per the JLS 7 at the bottom of section 7.6). Therefore if you want multiple public non-nested subclasses, they must all be in separate files.

package tessty;

public abstract class Item {

    int weight;

    public static class Apple extends Item {
        public Apple() {
            weight = 2;
        }
    }

    public static class Shoe extends Item {
        public Shoe() {
            weight = 3;
        }
    }

}

In summary, classes are:

  • top level if they are not enclosed in any other class
  • nested if they are enclosed in another class (nested can mean static or not, and declared as a member, local or anonymous class)

Within the nested set they are:

  • member if they are declared immediately within the class definition block
  • local if they are declared inside a method
  • anonymous if they are declared with an instance creation expression

And nested classes are either:

  • static member if they are static (therefore they must only be member)
  • inner if they are not static (these can be member, local or anonymous)

Inner classes receive an implicit reference to the instance of the parent that created it. Static member classes have no implicit knowledge of any parent instance.

Andy Brown
  • 18,961
  • 3
  • 52
  • 62