I am making a method to use on a array that has objects from 3 child classes of the same parent class. I want two of the classes to react differently, when third class does a certain action. Would I use a loop on the array with a .getClass() and a if-else-if statement as to what to do with each of the objects based off of the .getClass()?
While that would theoretically work, using if-else-if switches based on class's type is often considered a code smell.
There isn't a lot of extra info you give as to what sort of behavior and reaction you're looking for but as first step consider this: Can the "reaction" you want to get from the classes reasonably be considered to be a method of the class, and could it be a method of the parent class that the child classes override as needed?
(Think of the classical example with a class Animal and a method makeSound() and then a class Dog that overrides it to output Bark! and a class Cat that overrides it to output Meow!)
You might check here for a few ideas: https://refactoring.guru/smells/switch-statements
or provide extra info so we can figure out a good refactoring to avoid the switch block.
Related
When writing a program in Java, if I have a special case of an object that needs to be treated differently by the main class but that does not require any additional methods, is it better to add a boolean parameter to the constructor of the object such as isSpecial and to check whether the object is special in the main class or to create a new object that extends the original?
Example:
I have a Cat class. If a cat has whiskers, I want to print "This cat has whiskers!" in the Main class.
Would it be better to have a WhiskerCat class or to simply add a boolean parameter to the Cat constructor such as hasWhiskers?
Simply add the boolean parameter. You don't want to end up with an excess of classes that do roughly the same thing. For example, in the Cat class, the default value for hasWhiskers should be false, and remain false if they don't call the constructor that explicitly requires them to specify it. Then you can have a hasWhiskers() method that returns this boolean attribute.
In general, only extend a class if the new class has additional functionality (additional methods etc) that cannot simply be tacked on to the original.
It's a problem of responsibilities: which class is doing what?
Your "main" class should not probably be aware of the internals of the "Cat" class.
In your case that means the implementation of the Cat class would probably need to be adjusted to either have a new interface that the main class could use to print that message.
Then the Cat class itself could either have that boolean, a (list of) component that make up the cat or you could go the inheritance way. This will most likely depend on the real problem: is there many more variations? is that really the only difference? are you taking a class/exam? (in the last case it might be more useful to just apply the way you've been taught).
I think the problems are about design patterns instead of coding style.
In general,if you want to add some new features in a class.
First,you should ask yourself is it a interface or a property?If it is a property,then there are two ways to tackle it.
Way 1:subclass as you metioned
Way 2:you should use delegate (i.e. add a hairclass to consider whether it is a long hair cat
or it is short hair cat.)
Just wondering, is adding a boolean the only way to recognize if the object is special? For sure there must be other characteristics that make it special?
Anyway, it's not the responsibility of the main class to know if it is. Leave what should be printed to the Cat class, not on the Main class.
In my opinion it depends on how special that attribute is.
If we consider another example:
cars...
The attribute 'sunroof' or 'navi' is quite common and has no special requirement to the car and may be part of the base class.
But a siren and flash light are quite uncommon and would be better fit if they are attributes of another extended class.
Let's say we have something like this:
public abstract class MyClass {
//Stuff in here
}
public class MyClassA extends MyClass {
private String thingie; //Along with getter/setters, of course
//Other stuff
}
public class MyClassB extends MyClass {
private List<Integer> thingies; //Again, getters and setters to go with
//Other stuff
}
Let's assume we have any number of classes that extend MyClass, each with it's own instance variable of a different type, although some may have the same type. This is an unfortunate necessity. Now, let's assume we have a Collection of MyClass. We have a collection filled with any number of child classes, each with an object contained within. Let's say I need to iterate over this Collection, retrieve said object from any number of elements, and perform actions upon it, store it, manipulate it, send it elsewhere, etc. These objects have nothing in common aside from extending Object.
I might be able to simply delegate these actions into the MyClass children themselves, use a visitor, etc, but this likely isn't feasible as these actions may be dependent upon other MyClass children in the Collection. A single MyClass child likely won't dictate the action to be taken all by itself, or even any single Collection of MyClass. Some of these actions may be cumulative and dependent upon a number of other potential cumulative factors.
Is there any "good" way to handle this, or am I just going to be cursed to the hell of ugly typechecking conditionals or something similar? I considered using Generics in MyClass and using concrete types on all of the children. This could simplify the retrieval of objects, but would still necessitate a large conditional block.
You discarded in your question the "good" way of doing it. Generics will not help in this case. Yes, you are going to be cursed to a nasty place for the ugly use of type checking. You can disguise the type checking using a common instance member called, say, category and its corresponding accessor getCategory defined in MyClass. And them do a switch if you can (instead of multiple ifs) on getCategory(). However, the people who will condemn you could dislike ifs and switches no matter if they are checking for types or not. And they could also be smart and understand what you are trying to do. Anything but
for(MyClass e: collection )
e.doYourAction();
is "bad".
Now, for software that seems to have no specification at all, you could be pardoned.
Here is what you need to know to understand the question:
I want to connect a class called SCL to a class called Region.
Now I have many different ways I want to connect a instance of
these 2 classes.
Writing this is Java
There are no global variables in use
So I can either create several classes(about 9) that utilizes polymorphism but then each class has only one method called connect(...) with many different parameter lists. I think this is called a functor class.
For example a class "SCLToRegionOverlapCircleConnect" will have a connect method that looks like
public void connect(SCL scl, Region region, int radius, int overlapPercentage) {...}
while a class "RegionToRegionNonOverlapSquareConnect" will have a connect method that looks like
public void connect(Region bottomRegion, Region topRegion, int sideLength) {...}
OR
I can just make one class called ConnectionTypes and just have 9 different methods each with a different method signature.
What are the PROs and CONs of each implementation? Thanks!
If you use polymorphism, then you're determining the connection method when you instantiate the SCL object. Does that make sense? Or could an SCL class be connected to the Region in various different ways thoughout its life? In that case, polymorphism doesn't make sense. One important aspect that we have no information about is what happens to the parameters of the connect(...) method. Do they need to be stored in the SCL class, in which case with different parameters polymorphism might again make sense so that each class can store the appropriate parameters.
Another thought is, is the act of connecting an SCL class to a region really a method for the SCL class at all, or should it live somewhere else?
I suggest you to use the second.
less classes, so the project is clarelier than in the other way.
you don't need to move 9 classes when you want to use your
methods in another project (ex.), but only one class.
while programming, one rule is not to duplicate the code; using 9 classes,
you have to write 9 times the declaration, and maybe to declare 9
times the same global variables, using a lot more memory than using
one.
overloading, that means that if you have to make one thing
but in multiple ways (ex. you have to print some objects, and the
result will be one string, but you need to write it different for
one type of object, etc., you can use this technique) you can write
9 methods with the same name, same output, but different inputs.
inheritance: if you want to make a class that inherits those
methods, you MUST use only one class, because java does not support
multiple inheritance.
I can't see any CONs, except that you have to reinitialize the global variables to avoid problems.
Let me put two things straight:
You are thinking of the Command pattern, not the Functor pattern. The difference is that the latter also has a method to retrieve the return value, but your connect method is void.
The Functor pattern would not have a different signature for each of your connect methods; instead, each concrete class would have dedicated setters for the parameters (specific to the particular way you want to connect) and the same, parameterless public void connect() method. The latter would be the only method declared in the common Connect supertype.
I can throw in some example code if you want.
Pro: if it makes sense anywhere in your code to work with Connect commands without needing to know which of the 9 ways you're dealing with, then the Command pattern is your friend.
Con: you will have more code, and encapsulating pure functionality can reduce the understandability of your code quite a bit.
what are the benefits of using nested class in Java? In many examples it seems to me it only adds complexity to the design. Is there any example that shows the power of using nested class in comparison to for example composite pattern?
Why Use Nested Classes?
There are several compelling reasons for using nested classes, among them:
It is a way of logically grouping classes that are only used in one place.
It increases encapsulation.
Nested classes can lead to more readable and maintainable code.
(from the docs)
I think that the best case I can think of, off the top of my head would be the implementation of nodes in some sort of collection class (tree, linked list, map, etc). There is no reason why the node implementation should be exposed to the public, and since it is only used by the internals of your collection, it makes sense to make the node class nested inside the collection class.
Something along the lines of..
public class MyTree {
private class TreeNode {
//implementation details...
}
//public api, where implementation references TreeNode
}
I would use a nested class in a case, where I mostly need this class inside the surrounding class. This could be usages like event listeners.
Or in the case when I need to fulfill a specific interface as a parameter to an API method and only create this structure in this specific top level class.
This avoids the creation of more top level classes - messing your code base - that are not useful to any other class.
Hope this helps. :)
Is there any example that shows the power of using nested class in comparison to for example composite pattern?
Nearly all the Iterator implementations and the implementations for keySet() and values() are nested. The actual name is not important but they need access to the outer class to do their work.
Having these be top level classes wouldn't be elegant or encapsulated.
There are many examples I can think of to use nested classes
1- Extending a class for the purpose of using it just inside this instance with a different behavior than usual (overriding a method or more)
2- A short hand for implementing and passing an event listener to whatever method in one single step
3- Implementing a class that is too specific to be defined globally (or with package visibility or private or whatsoever). and you just want to hide it into the larger class
I do agree though that the usage of inner classes would complicate the code no matter how hard you try to make the for formatter beutiful but it has its uses, so as my own rule of thumb I only use inner classes when I'm sure that one of the above applies and that its size will be minimal in order not to vandalize my code
and for that mattar keep all the code minimal :)
We use nested (inner) classes when we know that this class will primarily be used only by the class that it will be written into. It keeps the package structure cleaner. Complexity is reduced by making use of an IDE where you can easily find classes that are not listed in the package structure.
As requested a real world example, take a look at the ArrayList implementation for the jdk.
You could find it here:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/ArrayList.java#ArrayList
You will find (among other things) the iterator class inside the Arraylist class. I would guess, the reason for this behavior (as for most of the iterable collection subclasses) is the direct connection between the collection and its iterator. You do not need it outside the class.
You can find nested class in more places inside the jdk.
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.