Understanding relationship between Java Super and Sub class constructors and methods - java

This may be a bit general and I apologize if it is too much so. It pertains to an assignment for a college class and as such would like to focus on my understanding of the topic as opposed to what the answer should be.
As I understand the situation:
I have one parent class called pet, and two subclasses called Dog and Cat. The UML class Diagrams specify that Pet contains the methods createPet(), updatePet(), and petCheckIn().
petCheckIn() requires the ability to create an object if it isn't already, and update one if it is.
The two subclasses contain default constructors, as well as setters and getters for their attributes, but nothing else specific to them.
I don't believe there would be an instance when a Pet object would be needed as the pets being checked in would always be dogs or cats. If constructors are not inherited by the subclasses but methods are, and createPet() is not strictly speaking a constructor, can an inherited method perform the constructor function if designed properly? I feel the implementation should be something like (not concerned about exact syntax as much as I am my understanding of what can and cant be done here):
My pseudocode :
Execute Dog/Cat inherited petCheckIn()
IF new pet THEN
Execute Dog/Cat inherited createPet()
ELSE
Execute Dog/Cat inherited updatePet()
This is an entry level programming class, and so I cant imagine that the implementation would be terribly complex.
Likely I am misunderstanding something/overcomplicating.
Regardless, Thanks for your time.
EDIT:
Truly sorry I never got back to you #Karam and #Chung. Life hits like a freight train sometimes lol. Specifying another class was out of scope for the assignment (though most of what I wanted to know seems to have been as well), nothing was specified about the signature (thats methodName + its arguments correct?). Ultimately I believe a lot depends on how the classes would be implemented by the overall program which was not covered in detail. I can pretty confidently say I was just asking questions that were beyond what was intended at that stage of the lesson plan. I wound up using a parametered constructor in the super class, and another in the subclass which passed arguments for superclass fields to the superclass constructor, then initialized the subclass specific fields. Karam, I never wound up actually defining the methods by which the constructors were called, and wasnt able to educate myself on design patterns, but a relative of mine also mentioned an abstract factory. Id say that is likely the best way to handle it. Unfortunately I do not have more time to dig into this right now so Im calling it good.
Cant tell yall how much I appreciate your willingness to help.
Dog.java constructor:
//Overloaded Constructor that passes parameters to Superclass
constructor.
//TODO: Reconsider which fields need a parameter and which can be set to
default at this point in the program.
//TODO: Verify that not passing an argument for catSpace will default to
-1.
//FIXME: Is dogSpaceNBR known at this point in program?
public Dog(int dogSpaceNBRInput, double dogWeightInput, boolean
groomingInput, String petTypeInput, String petNameInput, int petAgeInput,
int dogSpaceInput, int catSpaceInput, int daysStayInput, double
amountDueInput) {
// Passes arguments common to all pet subclasses to superclass
constructor.
super(petTypeInput, petNameInput, petAgeInput, dogSpaceInput,
catSpaceInput, daysStayInput, amountDueInput);
//Dog specific variables
dogSpaceNbr = dogSpaceNBRInput;
dogWeight = dogWeightInput;
grooming = groomingInput;
}

If i understand well your question , you want to be able to create different instances of your pet depending on the subclass using only methods
There is a Design Pattern called Abstract Factory , it is used to ignore the creation of different methods in a concret way
Example :
You have the class Pet ( it should be abstract ) that contains the method createPet() {}
In your sublcass , you'll have to simply redefine the method createPet() { return new Dog() ; /* or */ return new Cat() ;}
This helps you whenever you create a new sublcass , to redefine the methods without changing in the original class , and this will goes not only for the method createPet() but for all your methods

Related

Instantiating objects whose subclass will depend on user input

Please excuse the silly questions, I'm fairly new to Java and OOP and I'm trying to follow the Design patterns (avoiding ifs, switches, etc) but I'm having a hard time doing so.
So, I'm building a weapon vendor for a 'game' project of my own. This vendor has a list of objects. These objects are all different instances of the Weapon Superclass (e.g. Sword, Spear, Axe, etc).
When a user tries to buy a weapon, the vendor will show the weapon list and the user selects one by inputting its list index.
I'm now facing two problems:
1) How can I make an instance of an object whose subclass will depend on user input?
2) How can I invoke the right constructor, passing the same parameters of the weapon bought to the new object to be instantiated? I'm trying to do this in the most polymorphic way possible, avoiding ifs and switch statements.
So far, what I tried was making an Interface (iWeapon). Then, based on that interface I made a Factory that receives the type of a weapon (String) and returns a new instance of a weapon with the corresponding subclass.
This allowed me to instantiate a 'generic' weapon using the data type of the interface. However, I don't know if this is the optimal way of achieving this. Also, I don't know how to initialize the attributes of the new instance with the same values of the recently bought weapon, in a polymorphic way.
I tried creating a method 'getAttributesFromOtherWeapon' on all my weapon subclasses, that receives an object with the same types and simply copies these values. The problem I'm facing now is that the iWeapon type object I instantiate doesn't have this method, and if I include it on the interface I get an error on my subclasses saying that 'Class must either be declared abstract or implement abstract method '
My vendor code does something like this:
Weapon weaponToBuy = (Weapon) weaponList.get(weaponChosenIndex);
iWeapon newWeapon = weaponFactory.getWeapon(weaponToBuy.type);
newWeapon.getAttributesFromOtherWeapon(weaponToBuy);
However, since newWeapon is an iWeapon I needed to declare getAttributesFromOtherWeapon on its interface, which looks like this:
public interface iWeapon {
void getAttributesFromOtherWeapon(iWeapon iWeapon);
}
And now, in every Weapon subclass where I try to implement this method I'm require to pass an iWeapon instead of the corresponding Subclass type (Sword, Spear, etc.). Problem is that in my iWeapon interface I didn't define all the attributes corresponding to a Weapon (or any Weapon subclass) since I understand they'd be defined as constants.
I think there's probably an out of the box solution to this that I'm not seeing due to me being a noob on Java. Any help will be thoroughly appreciated
There are various solutions to this.
1. Use generics
interface Weapon<T extends Weapon> {
public Weapon getAttributesFromOther(T t);
}
class Axe implements Weapon<Axe> {
#Override
public Weapon getAttributesFromOther(Axe other) {
// TODO get those attributes
return this;
}
}
... etc.
Pros
Sword#getAtributesFromOther will only take a Sword, if the class is defined as implements Weapon<Sword>.
Cons
If by mistake, you declare something like class Dagger implements Weapon<Pitchfork>, then the getAttributes will take a Pitchfork.
Negligible in my opinion, as it's all compile-time, but worth considering.
Also your weapon references should change to Weapon<?> for unknown weapon types at runtime.
2. Declare a WeaponProperties class extending some parametrized Map, and a getter/setter pair in the Weapon interface
Pros
This will work granularily with all weapons, you just have to check whether the property is present.
You can easily merge properties common to multiple types of weapons.
Cons
Lots of boilerplate in all weapons, lots of "safety" code when copying properties from different weapon types if you allow that.
3. There probably is something even better - will edit if I have an idea
Notes
Make sure to follow Java code conventions, e.g. there's nothing wrong with Hungarian notation, but every type should always be CamelCase (contrary to variable names which are camelBack). This is about your iWeapon interface, which you can easily just refactor to Weapon - see example above.
Afterthought: I realized the getAttributes... methods in my example return Weapon, but that's not relevant to this case - you can safely return void instead

A design pattern for constructors

I have been challenged by a design issue which I will try to describe below.
Suppose that a class, call it A, has a constructor with a bunch of parameters. Since it is tiring and dirty to write all those parameters in each instantiation, I have written another class, call it StyleSheetA, which encapsulates all those parameters and is the only parameter to the constructor of A. In this way, I can prepare some default StyleSheetA templates to be used later, and if it is needed, I can modify them.
And at this point, I need to extend A. Suppose B extends A. B will have its own stylesheet, namely StyleSheetB. I think it will be appropriate that StyleSheetB extends StyleSheetA, so with one stylesheet parameter, constructor of B can also construct its super class A. But I am afraid of the possibility that this design may have flaws. For example what if I decide to add a getter/setter for the stylesheet? Is there a novel way to handle all these situations? Am I in the wrong way? For those who are confused, I attach some code here:
class A
{
StyleSheetA ss;
A(StyleSheetA ss)
{
this.ss = ss;
// Do some stuff with ingredients of styleSheet
}
}
class StyleSheetA
{
int n1;
int n2;
// :
// :
int n100;
}
class B extends A
{
B(StyleSheetB ss)
{
super(ss);
// Do some stuff with ingredients of styleSheet
}
}
class StyleSheetB extends StyleSheetA
{
int n101;
int n102;
// :
// :
int n200;
}
Thank you for any help or suggestions, also any of your critics will be appreciated.
Edit: I am developing in java me so there is no generics support.
It seems to me that you are only moving the problem of having too many parameters from class A to class StyleSheetA.
To illustrate my point, think of this question: How would you instantiate StyleSheetA? Probably using a constructor that accepts all these parameters, anyway. The only benefit this design may give you is if you have a same set of parameter values encapsulated by an object of StyleSheetA which you will reuse among multiple instances of A. If so, bear in mind that although you'd have different instances of A they would share the same parameters, so it isn't a good choice.
What I could recommend you is to try to refactor your class A itself. Try to break it up into smaller classes. If nesseccary, try to create subclasses to avoid conditional branches, etc.
Now, I don't know how your class A looks like, but maybe if you do so you'll have several classes, each with its own set of parameters. And if any of the parameters is a discriminator (meaning that it determines the class "type") you will be able to get rid of it, just by using subclasses, and relying on built in type system to do it instead.
Have you considered using an IoC container, like StructureMap, to manage your constructor dependencies? That might make a lot of this stuff easier.
A thoughts on the getter and setter issue:
The constructor in 'B' implies that the additional parameters (n101+) are necessary for the operation of the class. If you were just extending the class with a full parameter list, you would have getters and setters for n101...n200 in B and n1...n100 in A. This suggests perhaps not having StylesheetB extend StylesheetA, but rather have the constructor to class B be B(StyleSheetA,StyleSheetB), this way you can have a setter in class A for it's parameters, have that inherited and also put one in B for StylesheetB.

Immutability and Readability

So I've been reading Effective Java by Joshua Bloch and noticed two points which I actually have encountered in my work.
Point 1: Making setter methods to make code more readable.
In his example, we have a class with a ridiculously huge constructor. When people instantiate the class, it's hard to tell what's going on with all the parameters. Thus, he suggested making a minimalistic constructor and have setter methods for all other options, so instead of...
MyClass clazz = new MyClass(a, b, c,
d, e, f, g);
you would write....
MyClass clazz = new MyClass(a, b,
c); clazz.setDitto(d);
clazz.setEcho(e);
clazz.setFunzies(f);
clazz.setGumballs(g);
Which, as a huge supporter of readable code, I liked a lot.
Point 2: In general, he suggested having immutable classes. He goes into great depth on why having immutable classes is much better than having a class that could be in several different states. I can definitely say that he sold the idea to me, and I can't wait to make most classes I write from now on immutable, except....
What happens when you have an immutable class with a huge constructor? You can't make setter methods for it; that would break immutability. I tried skimming through the rest of the book, but I don't think he covers a solution for this.
There is the possibility of making one-time use setter methods, but just the fact that a setter method is available to a class that is supposedly immutability is disheartening, even if it does just throw an Exception if you try it subsequent times.
Does anyone have any good ideas on how to handle this problem? I'm currently facing this issue at work where I have an Immutable class with a huge constructor which I'd like to refactor to something that's more readable without breaking immutability.
One option is to provide a separate builder class that provides the setters, which is responsible for constructing the actual object.
In the second edition of Bloch's "Effective Java", item 2 illustrates this for an immutable class. The key ideas are:
The builder has a mutable field for each option.
The builder passes itself as a single argument to the immutable class's constructor.
Introduce Parameter Object, maybe? It kind of moves the problem around, but maybe in useful ways. Your parameter object needs no methods; it just holds the data, and you set it up, instead of your real class. Then your real class initializes itself in the constructor via the parameter object.
You can go with fluent interfaces: Building big, immutable objects without using constructors having long parameter lists
See also:
Constructor Parameters - Rule of Thumb
Having one request object as a Method Signature parameter, which constitute all the required parameters
How about having an abstract base class which supports getters but no setters for all the attributes of the class, a derived sealed "immutable" class whose constructor accepts a base-class object, and a derived mutable class which includes setters for all the properties?

Find info about class in java, software design?

I have a bunch of classes extending an abstract Base class.
Each subclass takes an array as in the constructor, (different length depending on class).
These classes could be written by other people.
What is the best way to figure out the length of the array the class needs?
I could:
(A) Require that each derived class have a static method, returning the length.
However, the base class cannot enforce this, since abstract static methods does not work in java.
(B) Each derived class have a constructor with no arguments, and I construct
such classes just to be able to call the countParameters() method, that
I can enforce from the Base class. This feels "cludgy", since I am not interested in creating such object, but only need some info about it.
The reason is that I am creating a GUI, that gives the user the ability to create
instances of Derived classes, but each Derived class takes different number of parameters.
That is, I need to know how to draw the GUI before I can create the classes.
EDIT:
I could just require that each Derived class have a private
constructor, with no arguments, and using reflection I can call the countParameters() method.
EDIT2: Actually, what I am interested in, is what the names of the parameters are.
That is, if the class Derived have the constructor
public Derived(double name1,double name2,...)
I need a way to generate the String[] array
{name1,name2,...}
I guess this would be impossible to do without creating an instance of the class,
but for the user to be able to create such class, he/she needs the parameter names!
Moment 22.
It sounds like you need the Factory Pattern.
In general, it's a bad idea for a base class to know the set of it's descendant's. So you define another class whose job it is to know that.
If you have something like a Shape, with ThisShape and ThatShape as derived classes, then a ShapeCreator will handle the job of creating the specific set of shapes your program supports, giving each one the arguments it needs.
It's not quite clear what you're trying to achieve, but I wonder: Do the subclasses really have to take a single parameter with an array, as opposed to a list of parameters?
Constructor<?> ctor = Test.class.getConstructors()[0];
int parameterCount = ctor.getParameterTypes().length;
ctor.newInstance(new Object[parameterCount]);
how about this code:
public absract Base {
public abstract int size();
public Base(Object[] objs) {
if (objs.length != size()) {
throw new IllegalArgumentException();
}
//rest of your code.
}
each child class needs to implement size method.
hope its help.
I'd go with method A. You can't get the compiler to enforce the existence of such a method, but you can certainly enforce it in your program - no method, no work!
Seriously, this whole scheme is a bit brittle and I can't think of a way to make it significantly better. An incorrect implementation of those subclasses will bomb out, that's life.
A possible remedy would be for you to provide a set of interfaces for those subclasses, such as
SubClassTaking2Args
SubClassTaking3Args
...
and requiring your sub's to implement one of those as a marker interface. But that's just more bureaucracy with little more effect.

Getting data from a subclass without instantiation

I have an abstract superclass and various subclasses. Each subclass contains a value that I would like to use statically but it is not possible to create an abstract static method. I want to get a value from them dynamically without having to create instances. What do I do?
Another question would be: How would I loop through subclasses? Is it it even possible?
One attempt involved mapping class names (Subclass.class) to the value and trying to use the newInstance on them so I could use a method to get the value but this doesn't work.
Where am I going wrong in my approach?
Why not go about it the other way? Put the data someplace statically accessible and have the subclasses get it from there?
Of course, the feasibility of this depends on the nature of the data but when you find yourself hitting this sort of barrier it often helps to step back and reexamine your assumptions.
-- MarkusQ
You can reference static members/methods via reflection, but there is not automatic way to find all subclasses of a class.
Consider providing the subclasses/instance factories/metadata classes via some other mechanism, such as ServiceLoader services or some other plugin framework.
Maybe you are looking for enums?
public enum Planet
{
MERCURY (2.4397e6),
VENUS (6.0518e6),
EARTH (6.37814e6);
private final double radius;
Planet(double radius)
{
this.radius = radius;
}
public double radius()
{
return radius;
}
}
You don't have to create enum instances yourself. Enums can have values, e.g. radius() in the example. You can add behaviour to them so they can act like normal classes, by defining abstract methods on them, e.g.
public enum Planet
{
...
abstract double weightOnSurface(double weight);
...
}
You can loop through enums, like this:
for (Planet p : Planet.values())
{
System.out.println(p.radius());
}
So they seem to meet all your criteria.
Creating a second class for each of your subclasses which represents the type of that subclass might work.
For example, create a factory class for each subclass (a class that is responsible for creating instances of that subclass). There only needs to be one instance of each factory class.
Each factory class can then be responsible for knowing the subclass-specific data you describe. You then just need to loop over a fixed set of factory classes.
If you have a fixed set of subclasses then you can put the data in the superclass. If you subclasses can be added, then there is no way to list them all. You might get subclasses let the superclass know of their existence from the static initialiser (or use an agent!).
Generally superclasses should not be aware of their subclasses. However you might want to think (or better refactor) your superclass into a supertype and some other class responsible for your subclasses.
You will need to to scan package(s) and clasess to find ones that extend your superclass - unfortunately, this cannot be done with the Reflection API, but must be done through URLs (file system classes, jar files etc). Annotation use is probably better in this case, and lots of open source products use this method (Hibernate etc).
Then you can have a static method in each (either consistent naming or annotated) which you should be able to invoke with as method.invoke(MyObject.class, arguments)
The other option is to put a registry map in the abstract class - if you need to mandate it, the abstract constructor takes the static value (or just stores the subclass if calculations are needed). If you're controlling all subclasses, just make sure you have a static block in each one to add it to the registry.
Mapping subclasses... you can do it via reflection (but it won't be fun).
newInstance() (likely) won't work unless:
the class is public
the constructor is public
the constructor takes no arguments
The last one is mandatory, the other two depend on what package you are doing things from (I think, been a while since I cared). Using the Constructor class is better.
Can you give a short code example of what it is you are thinking of doing? Based on that I (and others) might be able to give you better answers. If you do need to do the mapping subclass thing I can dig up some code that does it...

Categories