Reputation: 158
If I have a non-static inner class, I know that it cannot contain static methods, because it requires an instance of the enclosing class in order to be accessible. However, is there any way to create a method that can be referenced with an instance of the outer class but not the inner one? Something along the lines of:
public class Family {
public final Set<Dog> pets = new HashSet<Dog>();
public class Dog {
public Color color;
public int weight;
public int height;
public Dog(Color color, int weight, int height) {
this.color = color;
this.weight = weight;
this.height = height;
Family.this.pets.add(this);
}
public void addDefaultBlack() {
new Dog(Color.BLACK, 10, 10);
}
public void addDefaultWhite() {
new Dog(Color.WHITE, 5, 5);
}
}
}
In such a way that I can reference it something like:
Family family = new Family();
family.Dog.addDefaultBlack();
...by requiring an instance of the outer class, but not the inner one. In a case such as this, Dog
is not a static inner class because each dog must belong to a family, but I want some methods that could create dogs with some default properties and add it to the Family
object of the enclosing class. The only way I could think to do this currently is to create an enum (such as something like DefaultDogs
) and pass it as an argument in a new constructor, then switch-case it to apply the properties. That seems somewhat messy, so I'd prefer to avoid it. Is there a way to do this with methods as I've shown? What's the correct syntax? Sorry if I'm missing something obvious here.
EDIT: I'm aware I could put a method in the outer class, but for readability and logic it makes more sense to me to keep it in the inner class in my opinion. Is that the only way to make this work?
Upvotes: 0
Views: 210
Reputation: 40044
The following will do what you want. But you will need to pass an instance of the Family
class to the method to be used to create a new instance of the Dog
class. The addDefault
classes can be declared static so they can be indirectly accessed vi Family.Dog
.
import java.awt.Color;
import java.util.HashSet;
import java.util.Set;
public class FamilyDemo {
public static void main(String[] args) {
Family family1 = new Family();
Family family2 = new Family();
family1.new Dog(Color.orange, 70,40);
family2.new Dog(Color.green, 100,200);
Family.Dog.addDefaultBlack(family1);
Family.Dog.addDefaultWhite(family2);
System.out.println(family1.pets);
System.out.println(family2.pets);
}
}
class Family {
public final Set<Dog> pets = new HashSet<>();
public class Dog {
public Color color;
public int weight;
public int height;
public Dog(Color color, int weight, int height) {
this.color = color;
this.weight = weight;
this.height = height;
pets.add(this);
}
public static void addDefaultBlack(Family instance) {
instance.new Dog(Color.BLACK, 10, 10);
}
public static void addDefaultWhite(Family instance) {
instance.new Dog(Color.WHITE, 5, 5);
}
public String toString() {
return color + ", " + weight + ", " + height;
}
}
}
I thought about this some more and have a few ideas for you to consider.
Color
. It is not use friendly for descriptive purposes. Create an enum for the Color and require it be used as an argument in the constructors. You can always add more colors and not affect someones existing implementation.Dog class
to Pet class
. Then you can have an enum of possible pets. You can even have the enum types provide ranges for the pets to enforce invariants in the values. For example, if you allow a tarantula
as a pet you wouldn't want to allow it to be 100 lbs. (yikes!). More pets can be added by simply adjusting the enum. Min and max values and others can all be specified as arguments to the enum types.PetFactory
with a custom setting as well as standard default pets. Then leave it up to the using class to add the pet to the set.Upvotes: 1
Reputation: 103018
The addDefaultBlack
method would have to be an instance method of the outer class, you'd call family.addDefaultBlackDog()
. Probably not what you were looking for.
Upvotes: 0