Java method that requires instance of enclosing class but not inner class - java

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?

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.
Unless you are planning on drawing the pets, don't use 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.
Change 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.
Finally, not only Families can have pets, but single people and even organizations. The root of your initial problem was having the inner class add an instance of dog to the enclosing class's Dog set. Why not just have a Pet class external to Family, useful by others. You could make it a 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.

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.

Related

Instance variables inside an Abstract Class ****Eclipse malfunctioned, this question is pointless****

So in a challenge in class, we had to use a public abstract Class Cycle as the parent class and create subclasses off of it. I used Unicycle Class as an example.
My professor refuses to let me put Color color as protected. He wants it private. He said the way that I can get the privacy issue worked out was by implementing the getter and setter for color. Initially they were set as abstract Color getColor() and abstract void setColor(Color color) but I tried implementing them inside the abstract class by making them public and giving them the method body.
The test in the code is:
cycle.setColor(Color.RED);
assertEquals(Color.RED, cycle.getColor());
I continue to get the error message,
The field Cycle.color is not visible
I know it works with protected but I have to use private.
Anyone have any hints they can throw at me here? I am going nuts with all of my research and failed trials.
public abstract class Cycle
{
//Declare instance variables
private String make;
private Color color;
//Create a constructor that only contains an argument for make
public Cycle(String make)
{
this.make = make;
}
//Create a constructor that contains an argument for make and color
public Cycle(String make, Color color)
{
this.make = make;
this.color = color;
}
//Create getter and setter methods
abstract int getNumberOfWheels();
//*********Was abstract Color getColor();
public Color getColor()
{
return color;
}
//*********Was abstract void setColor(Color color);
public void setColor(Color color)
{
this.color = color;
}
final String getMake()
{
//return the make of the object
return make;
}
Unicycle Class
public class Unicycle extends Cycle
{
//Create a constructor that only holds the argument make
public Unicycle(String make)
{
//Call on the super (parent) class to create the object with arguments
super(make);
}
public Unicycle(String make, Color color)
{
super(make, color);
}
//Create a method to get the number of wheels and return 1 since a unicycle only has 1 wheel
public int getNumberOfWheels()
{
return 1;
}
}
color is not visible to sub-classes since color is private in Cycle, so having a getter/setter in the Unicycle class results in a compilation issue.
Cycle already defines a getter/setter for color, and Unicycle is-a Cyle, so there's no need to attempt to override the getter/setter in sub-classes.
Remember that any public (or protected) method defined in a base class is available to sub-classes. This is one of the benefits of using inheritance.
My professor refuses to let me put Color color as protected. He wants
it private. He said the way that I can get the privacy issue worked
out was by implementing the getter and setter for color.
In case you were wondering if he is being difficult, I can tell you that he is trying to teach you a very important concept of Object-Oriented Programming. And that is limiting the scope of your variables in this case. You don't EVER want to give direct access to the data members of a class unless they are CONSTANTS. There are a few reasons for it, one of which is in case you need to add preliminary steps in the future before returning the value (i.e. return a value from an alternate source).
Now, you have something like this:
public abstract class Parent {
private String something;
protected Parent() {
something = "N/A";
}
protected String getSomething () {
return something;
}
protected void setSomething (String something) {
this.something = something;
}
}
public class Child extends Parent {
// bad use of override
#Override
public void setSomething (String something) {
super.setSomething(something);
}
// bad use of override
#Override
public String getSomething() {
return something;
}
public static void main (String[] args) {
Child child = new Child();
child.setSomething("New value");
System.out.println(child.getSomething());
}
}
public class Unrelated {
public static void main (String[] args) {
Parent child = new Child();
child.setSomething("Foo");
System.out.println(child.getSomething());
}
}
This works.... The field in the abstract class is private. Therefore, it is blocked from direct manipulation. The child classes can override a protected method of the abstract (parent) class and make it public for unrelated classes to call freely. I included a main method in both the child class and the unrelated class to illustrate this point.
The reason why the override is bad is because it doesn't do anything... HOWEVER, protected methods are restricted to be called outside the package or by classes unrelated to the class declaring the protected method. Therefore, if the unrelated class was outside of the package, it would not be able to call these protected methods. THEREFORE, you must override them by the child classes and make them public. THAT SAID, if this is the case, you could argue that the best thing is to make the protected method public in the parent class and avoid forcing implementing classes to override protected methods just for this reason.

Creating Objects According to an Input File

I have a task that needs to be done but I am really stuck.
Basically, I've some inheritance relations like this:
Animal
Pet WildAnimal
Bird Cat Dog Fish ||Snake Eagle
Animal is the parent of Pet and Wild Animal.
Pet is the parent of Bird, Cat, Dog, Fish.
WildAnimal is the parent of Snake and Eagle.
The task wants me to read inputs from a file which is "input.txt" and create Animal objects.
"input.txt" is like:
kiwi Bird
charlie Eagle
mango Fish
pepper Dog
angle Cat
tweety Bird
bob Dog
ziggy Snake
I can get all of the names but I couldn't figure out how to understand which kind of object every single name represent.
Here is the main method:
public static void main(String[] args) throws IOException {
String s ="";
int nameCounter = 0;
Animal[] animals = new Animal[100];
try{
Scanner input = new Scanner(Paths.get("input.txt"));
while (input.hasNext()) {
s = input.next();
Animal animal = new Animal(s);
animals[nameCounter] = animal;
nameCounter += 2;
}
}catch(Exception e){
e.printStackTrace();
}
}
Here is the animal class:
public class Animal {
private String name;
private int numberOfLegs;
private int numberOfWings;
public Animal(String name){
this.name = name;
numberOfLegs = 4;
numberOfWings = 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumberOfLegs() {
return numberOfLegs;
}
public void setNumberOfLegs(int numberOfLegs) {
this.numberOfLegs = numberOfLegs;
}
public int getNumberOfWings() {
return numberOfWings;
}
public void setNumberOfWings(int numberOfWings) {
this.numberOfWings = numberOfWings;
}
public void talk(){
System.out.printf("<Silence>");
}
public void fly(){
System.out.printf("%s cannot fly", getName());
}
public void run(){
System.out.printf("%s is running", getName());
}
}
I can add all the other classes if you want but i don't think you're gonna need them.
You have to instantiate objects of your specific class; based on the incoming string.
Example: if the class name from the file is Bird ... then you have to call new Bird() somehow.
There are two ways to get there:
Using reflection (you can actually instantiate classes "by string"; without knowing anything about that class)
By using a switch statement
Reflection is more of an "advanced" topic (and very easy to use the wrong); so I really do recommend you to go for option 2, like:
private Animal createAnimalFor(String className, String animalName) {
switch (className) {
case "Bird": return new Bird(animalName);
...
default: throw new IllegalArgumentException("Dont know how to create object for unknown class: " + className);
}
}
(the above code is meant as "fyi" - I didn't run it through the compiler; it is meant to give you one idea how this could be done).
Some notes beyond that:
Consider using a final field for those properties of your objects that can't change. You don't need a setter for the name then; just give the name as parameter to the constructor. In other words: only make those fields "changeable" that make sense to be changed. Anything else should better be final.
Instead of using an array with 100 empty slots, you could use a java.util.ArrayList and just add as many new animals as you find in that file.
Consider adding equals/hashCode methods to your Animal class (not mandatory, but you should read why that makes sense very often).
Probably most importantly: consider not putting all those different methods directly into your base class. It might make more sense to create either abstract subclasses that add certain functions, or use interface, like interface FlyingAnymal { void fly() }; which your specific subclasses would then implement. It is not really good practice to put a lot of methods on your base class ... that simply dont make sense for all of the sub classes.
If you really want to use reflection to do so (which I would also discourage), here's sample code :
String name = input.next();
String className = input.next();
// apply transformations to className as needed
Class<Animal> c = (Class<Animal>) Class.forName(className);
Constructor<Animal> constr = c.getDeclaredConstructor(String.class); // retrieves the Animal(String name) constructor
Animal a = constr.newInstance(name);
I don't think the code is so complex, but few people have ever used reflection so they'll have problems maintaining it, and it is tightly coupled with your classes definitions so it will probably have to be maintained a lot.

Java Subclass Constructor Assigning Values

I'm trying to create an object using a constructor from a subclass but I can't assign values to that object in the subclass Constructor.
Here is the superclass.
public class Bike
{
String color = "";
String type = "";
int age = 0;
public static void main (String [] args)
{
}
public Bike (String s, int i) // Constructor
{
color = s;
age = i;
}
public void PrintBike ()
{
if (type == "")
{
System.out.print(" You didn't give the proper kind of bike.");
}
else
{
System.out.print(" Your bike is a " + type + " bike. \n");
}
}
}
This is the subclass.
public class BikeAdv extends Bike
{
private String type;
public BikeAdv (String color, int age, String BikeType)
{
super (color, age);
type = BikeType;
}
}
Here is the class that calls the constructor.
public class Green
{
public static void main (String [] args)
{
Bike greenBike = new BikeAdv ("Green", 20, "Mountain");
greenBike.PrintBike();
}
}
When I run the class "Green", the output is " You didn't give the proper kind of bike." whereas I would expect to see "Your bike is a Mountain Bike".
Thanks!
The type field in the subclass shadows the type field in the superclass. The field in the superclass is never populated, and that's the one being checked.
If you simply remove the field in the subclass, the assignment there will populate the superclass field, and your code will likely work as you expect.
As noted in other answers though, it would be better to have the fields private or protected according to your need rather than default visibility.
You have declared these attributes without explicit visibility:
String color = "";
String type = "";
int age = 0;
Also, you have type redeclared in BikeAdv, that is probably an error (you don't need to).
If you want to have these attribute only accessible from its class, then you should declared them private. But, in that case, you have to parametrize the constructor to be able to modify all of them. Or maybe create setters for them (be aware that this way you will grant accessibility from outside the class).
private String color = "";
private String type = "";
private int age = 0;
If you want them to be unmodifiable from outside its class, but accessible from its subclasses, then declare them as protected:
protected String color = "";
protected String type = "";
protected int age = 0;
As you can see, there are a lot of possibilities. Check them out here:
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
The class Bike is not abstract or an interface, that means that all of it's methods are as they said in the Bike class. When you assign greenBike to be a Bike, not a BikeAdv you tell it to use the methods in the Bike class, instead of the BikeAdv class. Your best bet would be to make Bike abstract and leave the PrintBike void without a body.
Also: you never pass the BikeType String to the super class so there is no way it can receive it.

Java OOP issue - Related to Interface/Abstract Classes

I'm stuck with a Java OOP problem. I have come up with some toy code to explain the problem. Here are my classes -
Class 1 - Car.java
public class Car {
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo("Car", 4, problem); //4 is number of wheels
}
//bunch of other methods
}
Class 2 - Truck.java
public class Truck {
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo("Truck", 6, problem);
}
//bunch of other methods
}
Class 3 - ReportUtil.java
public class ReportUtil {
public static void reportVehicleInfo(String name, int wheels, String problem){
System.out.println(String.format("%s %s %s", name, wheels, problem));
}
}
Class 4 - Test.java
public class Test {
public static void main(String[] args) {
Car c = new Car();
c.reportProblem("puncture");
Truck t = new Truck();
t.reportProblem("engine missing");
}
}
I want to abstract the "reportProblem" method implementation in "Car" and "Truck" to a parent class. This is what I did -
Class 1 - Vehicle.java
public abstract class Vehicle {
public String mName;
public int mNumWheels;
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo(mName, mNumWheels, problem);
}
public void setName(String name){
mName = name;
}
public void setNumWheels(int numWheels){
mNumWheels=numWheels;
}
}
Class 2 - Car.java
public class Car extends Vehicle {
//bunch of other methods
}
Class 3 - Truck.java
public class Truck extends Vehicle {
//bunch of other methods
}
Class 4 - ReportUtil.java (No change made to this class).
public class ReportUtil {
public static void reportVehicleInfo(String name, int wheels, String problem){
System.out.println(String.format("%s %s %s", name, wheels, problem));
}
}
Class 5 - Test.java
public class Test {
public static void main(String[] args) {
Car c = new Car();
c.setName("Car"); //NOTE : Can be missed!
c.setNumWheels(4); //NOTE : Can be missed!
c.reportProblem("puncture");
Truck t = new Truck();
t.setName("Truck"); //NOTE : Can be missed!
t.setNumWheels(6); //NOTE : Can be missed!
t.reportProblem("engine missing");
}
}
This achieves what I want (I have abstracted the implementation of "reportProblem"). But I know this is not the best way to do it. One reason is that the "reportProblem" method should not be called without calling "setName" and "setNumWheels" methods. Otherwise 'null' will be passed. Is there a way of enforcing, using some OOP technique, the two methods calls (setName and setNumWheels) BEFORE reportProblem is called?
I hope I have made myself clear. If I am not, just let me know how you would have done it so that I can learn from it.
Yes, make name and numWheels final and assign then in the constructor. So...
Class 1 - Vehicle.java
public abstract class Vehicle {
public final String mName;
public final int mNumWheels;
protected Vehicle(String name, int numWheels){
this.mName = name;
this.mNumWheels = numWheels;
}
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo(mName, mNumWheels, problem);
}
...
}
Class 2 - Car.java
public class Car extends Vehicle {
public Car(){
super("Car", 4);
}
//bunch of other methods
}
Class 3 - Truck.java
public class Truck extends Vehicle {
public Truck(){
super("Truck", 6);
}
//bunch of other methods
}
Also, public fields are not good OO practice, because they expose details of your class' implementation that could be modified by users of the class. Those fields should be private. If the clients of the class need to know about them (or change them), then you should allow public getter (or setter) methods.
If you want to set the fields "required", you can set them as parameters in Truck/Car constructors and not provide a default constructor for these classes.
If members are essentials for an object's state/functionality, put them as part of a constructor, so it is not possible to create an object (and call the method of concern) without providing proper values for these members.
But you should not also provide a no-args constructor.
If there are too many parameters needed consider looking into the Builder idion
In addition to #Tony's answer (+1) if you have to use bean notation (default constructor and setters) and still do not want to allow using any business methods before the object is initialized you can do the following.
Define abstract method checkInitalized() in your Vehicle class. Implement this methods for your Car and Truck. BTW this method will probably have default implementation in Vehicle. In this case do not forget to call super from its overridden versions.
checkInitalized() should throw exception (e.g. IllegalStateException) if not all required fields are initialized.
Now call this method in the beginning of each business method. This will prevent you from using object that is not initialized yet.
This technique is a little bit verbose. Probably using wrapper pattern or AOP (e.g. AspectJ) may be useful here.

Refactoring abstract Java class with many child classes

I'm looking for ideas on the best way to refactor this scenario (better design, minimal effort).
Starting from the following example abstract class (actual has many more fields, methods and abstract methods) :
abstract class Car
{
private int manufactureYear;
// ... many more fields that are hard to clone
public Car(int manYear)
{
this.manufactureYear = manYear;
}
abstract public Color getColor();
abstract public int getNumCylinders();
}
There are so many child classes (say 100) that extend this class. These child classes are considered like 'specs' for the cars. Here are two examples :
class CarOne extends Car
{
private static Color COLOR = Color.Red;
private static int CYLINDERS = 4;
public CarOne(int manYear)
{
super(manYear);
}
public final Color getColor();
{
return COLOR;
}
public final int getNumCylinders()
{
return CYLINDERS;
}
}
class CarOneThousand extends Car
{
private static Color COLOR = Color.Black;
private static int CYLINDERS = 6;
public CarOneThousand(int manYear)
{
super(manYear);
}
public final Color getColor();
{
return COLOR;
}
public final int getNumCylinders()
{
return CYLINDERS;
}
}
During runtime car objects get instantiated and used:
CarOne carObject = new CarOne(2009);
carObject.getColor();
carObject.getNumCylinders();
However, after getting some external data, I discover that the car was repainted and the engine changed. The new specs for the car become:
class ModCar extends Car
{
private static Color COLOR = Color.Blue;
private static int numCylinders = 8;
public ModCar (int manYear)
{
super(manYear);
}
public final Color getColor();
{
return COLOR;
}
public final int getNumCylinders()
{
return numCylinders;
}
}
So really need to "apply" these specs to the new carObject without modifying existing fields such as manufactureDate. The problem is how to minimize the code of changes to those 100+ child classes (preferably leave them untouched) while being able to update the carObject during runtime.
N.B. I was given to work on this code so I didn't write it in this condition to begin with.
Based on the description and example, you are using inheritance inappropriately. It looks like you are creating many classes where you should be using a single class and many object instances. If this is true, you also don't need a design pattern to solve the problem. Without further clarification of the problem, this should suffice:
class Car
{
private int manufactureYear;
private Color color;
private int numCylinders;
public int getManufactureYear() { return manufactureYear; }
public void setManufactureYear(int manufactureYear) { this.manufactureYear = manufactureYear; }
public Color getColor() { return color; }
public void setColor(Color color) { this.color = color; }
public int getNumCylinders() { return numCylinders; }
public void setNumCylinders(int numCylinders) { this.numCylinders = numCylinders; }
}
Example usages:
// make a blue 6-cylinder:
Car blue6 = new Car();
blue6.setColor(BLUE);
blue6.setCylinders(6);
// make a red 4-cylinder:
Car red4 = new Car();
red4.setColor(RED);
red4.setCylinders(4);
// Uh-oh, they painted my red car!
red4.setColor(YELLOW);
If you want to minimize changes, you could use my refactored Car class from above, and then clean up the child classes so they leverage it. Something like:
class CarOne extends Car { // extends my version of Car...
private static Color COLOR = Color.Red;
private static int CYLINDERS = 4;
public CarOne() {
setColor(COLOR);
setNumCylinders(CYLINDERS );
}
// getters deleted, base class has them now
}
Since there is in fact a base class, my guess is that 99% of the code does not reference the concrete car classes (only the base class), so you should be able to change things fairly easily. Of course, hard to say without seeing the real code.
It depends on how much control you have over the code that creates these objects. I'm going to assume that this design exists for a reason that was kind of lost in the car example, but if the objects are created by calling new, then there is little you can do other than change them, although you could use the rest of this answer to suggest a more flexible way to change them.
If you can control their creation, then a factory that uses composition and returns a different kind of car object that overrides the specific parameters you care about and calls the original for the rest would allow you to affect your changes on a specific instance without changing all of the original classes. Something like:
Car carOne = CarFactory.makeCar("CarOne", 2009);
Then inside that makeCar method, you can decide whether or not to return a CarOne object, or a composite implementation:
public class CompositeCar extends Car {
private Car original;
private Color myColor;
public CompositeCar(Car original, Color myColor) {
this.original = original;
this.myColor = myColor;
}
public int getYear() { return original.getYear(); }
public Color getColor() { return myColor; }
}
I'd also recommend taking a look at the Builder Pattern if you have cases (or entire groups of classes) which have complicated construction logic, especially if some fields are required in some Cars, and different sets of fields are required in others.
Your subclasses do not provide different behavior only different data.
Hence you should not use different subclasses only different arguments.
I would suggest add a "getCar" method to your base case and use it as an a factory method.
Add the Color and Cylinder properties and load them from ... anywhere it suits your needs, it may be a database, a properties file, a mock object, from the internet, from a cosmic place ... etc.
Before:
Car car = new CarOne(2009); // Using new to get different data....
carObject.getColor();
carObject.getNumCylinders();
After:
class Car {
// Attributes added and marked as final.
private final Color color;
private final int numberCylinders;
// original
private final int manufacteredYear;
public static Car getCar( String spec, int year ) {
return new Car( year,
getColorFor( spec ) ,
getCylindersFor(spec) );
}
// Make this private so only the static method do create cars.
private Car( int year, Color color, int cylinders ) {
this.manufacturedYear = year;
this.color = color;
this.numberCylinders = cylinders;
}
// Utility methods to get values for the car spec.
private static final getColorFor( String spec ) {
// fill either from db, xml, textfile, propertie, resource bundle, or hardcode here!!!
return ....
}
private static final getCylindersFor( String spec ) {
// fill either from db, xml, textfile, propertie, resource bundle, or hardcode here!!!
return ....
}
// gettes remain the same, only they are not abstract anymore.
public Color getColor(){ return this.color; }
public int getNumCylinders(){ return this.numberCylinders; }
}
So instead of create a new car directly you would get it from the getCar method:
Car car = Car.getCar("CarOne", 2009 );
....
I wouldn't recommend you to make your car "mutable" for it may bring subtle undesired side effects ( that's why I mark the attributes as final ) . So if you need to "modify" you car, you better assign new attributes:
Car myCar = Car.getCar("XYZ", 2009 );
.... do something with car
myCar = Car.getCar("Modified", 2009 );
//-- engine and color are "modified"
Additionally you may even map the whole car so you only use one instance.
By doing this you don't have to add setters to your code. The only thing you have to do would be search and replace
Car xyz = new WhatEver( number );
For
Car xyz = Car.getCar("WhatEver", number );
And the rest of the code should run without changes.

Categories