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.
Related
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.
I have an assignment to build a self evaluation test grader. The teacher gave us test interfaces:
and question interfaces:
to implement, and I don't know whether I'm supposed to implement them all in one class like this:
public class CQuestion implements IQuestion, IQuestionMultipleChoice,
IQuestionNumeric, IQuestionYesNo,IQuestionMetadata {}
public class CTest implements ITest,ITestStatistics {}
or whether I should do one class for each question type.
I tried the first approach but I get errors because there are methods with the same name.
I want try the second approach, but I don't know how to do it. I know I have to create a question object inside the test class, but I don't know whether I if have to create one object for each question type.
In the case of the test interfaces, I don't see why you couldn't (at first glance), and I think you should implement both interfaces.
In the case of the question interfaces, as you've found out, there are incompatibilities in the method signatures. Since IQuestionMultipleChoice, IQuestionNumeric and IQuestionYesNo all extend IQuestion, you only need to implement one of the first three. As #john-bollinger pointed out in the comments, there is no need to implement IQuestion if you implement one of the three dub-interfaces.
I think you should also implement IQuestionMetaData, with something like that
public class CQuestionYesNo implements IQuestionYesNo, IQuestionMetaData {
... // your code here
}
I don't know whether I'm supposed to implement them all in one class [...] or whether I should do one class for each question type.
I tried the first approach but i get errors because there are methods with the same name
... and arguments, but different return types. Let's apply some simple logic here, then: if two interfaces have conflicting requirements, then they cannot both be implemented by the same class. Thus, it appears that there must be separate concrete classes implementing IQuestionMultipleChoice, IQuestionNumeric, and IQuestionYesNo. Because all those interfaces extend IQuestion, each of those implementations will also necessarily implement IQuestion, so there seems no inherent need for a separate implementation of that. Nevertheless, it would be fairly natural to have a base class for the others that implements IQuestion directly.
Inasmuch as IQuestion has methods to get and set metadata, it does not look like it would be useful for any of the aforementioned classes to implement IQuestionMetaData. There should surely be a separate class for that.
Similarly, ITest has methods to add and remove IQuestions and to provide ITestStatistics, so it does not appear that a typical implementation of the former would also implement either of the latter. It appears, then, that there should also be separate implementations of ITest and ITestStatistics.
I want try the second approach, but I don't know how to do it. I know
I have to create a question object inside the test class, but I don't
know whether I if have to create one object for each question type.
Why would an ITest implementation need to create question objects? It has methods with which a separate object can add and remove questions. I see no reason to think that a test is expected to be able to create its own questions.
Important note:
You said that your job is to implement a grader, but none of the above appear to be part of the implementation of a grader. Those interfaces seem instead to describe the subject on which your grader will operate. That does not necessarily mean that you're not expected to implement those interfaces, but you should make sure of that before you put in the work. From my perspective, it is entirely possible that you're expected to rely on the interfaces in your grader implementation, but not to provide your own implementations of them.
I am pretty new to Java, so I may be using incorrect terminology. I am trying to gracefully extend a class to a new class which holds multiple instances of the superclass. For example, say I have a class
class Rose{
String smell;
Rose(String smell){this.smell=smell;}
void sniff(){ println("smells "+smell);}
}
And I want to define a class like...
class Bouquet extends Rose{
ArrayList<Rose> roses;
...
}
holding multiple roses. My actual code has something like 20 methods, and for most of them the extended method would be
void sniff(){
for( Rose one: roses) one.sniff();
}
Is there a way to construct bouquet in such a way that I don't need to explicitly define these silly loops? I'm not tied to ArrayList, I could even make a new super class if that's the way to go about it. However, it is important that I can send a bouquet instead of a rose argument to externally written methods.
EDIT:
Haha, I think my flower metaphor was a big fail. :) But your input is good; you guys have clarified my thinking a bit.
In my real problem, there are a set of operations that define how to add instances of the base class together into a new instance of the base class. Perhaps a better metaphor would be twisting a number of small fabric strands together into one rope. External methods should treat a rope and a strand exactly the same.
It does seem like extends is wrong, any other suggestions?
You dont really need to extend bouquet from roses. You extend only when there is an IS A relationship, like you have Flower class and Rose is a Flower. But bouquet is not a rose. Ideally you should have a bouquet class which HAS many roses. If there is a 1:N relationship, then you will have to loop through to get individual items.
Although we can implement anything to our desire, but there are few flaws in your class designs in regards to abstraction.
A bouquet is a collection of rose, so it shouldn't extend rose, but rather have it as a List inside it, which you have anyway. It doesn't make much sense to extend on rose and also have it as property inside bouquet. Instead, create a Base class called Flower and then extend that to create rose.
Define the sniff function inside Flower Class, making provision to override it in derived class, if you need to do that.
It would be wrong.
I would have voted Shamims answer up, if he hadn't introduced the flower class, which is not a reasonable assumption from your question.
ArrayList <Rose> bouquet;
might be all you need. But you can't use a Bouquet as a Rose. Bouquet.split (); could make sense, but Rose.split would be a very different thing.
The is-a question gives you a rough idea, whether inheritance is a reasonable thing. It's not always the final answer, but if it doesn't fit, it doesn't.
Okay, correct me if I'm wrong, but to me it seems quite obvious that the real question has nothing to do with flowers or roses, but the author is simply trying to create an example.
In a real application there could be an is-a relationship and the problem is valid. For example, I have had to use this pattern when handling callbacks: you have one MyCallback interface, a couple of concrete implementations, and to be able to register multiple callbacks you have a MultipleMyCallback class that has a list of MyCallback it delegates all calls to. You get exactly the same annoying for loop in every method.
I think you could do this via a Java dynamic proxy. Or if you're feeling adventurous even using something like CGLIB But I recommend against it. Just accept that this is a fact of life with Java and write the 20 methods and be done with it.
Without a lot of hacks, no, there is no easy way to do this. I'd highly recommend reading about this. Basically, you only want to use inheritance to enforce an is-a relationship - what this means is that your subclass should be substitutable for your base class in all situations. The natural question is therefore, is a bouquet a rose, and the answer here is no, it is not, thus inheritance is not suitable for the job.
In addendum to the answers posted, when it comes to naming your methods it will be better if you replace the sniff() method with getSmell().
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.
In my quest to correctly grasp Interface best practices, I have noticed declarations such as:
List<String> myList = new ArrayList<String>();
instead of
ArrayList<String> myList = new ArrayList<String>();
-To my understanding the reason is because it allows flexibility in case one day you do not want to implement an ArrayList but maybe another type of list.
With this logic, I set up an example:
public class InterfaceTest {
public static void main(String[] args) {
PetInterface p = new Cat();
p.talk();
}
}
interface PetInterface {
public void talk();
}
class Dog implements PetInterface {
#Override
public void talk() {
System.out.println("Bark!");
}
}
class Cat implements PetInterface {
#Override
public void talk() {
System.out.println("Meow!");
}
public void batheSelf() {
System.out.println("Cat bathing");
}
}
My question is, I cannot access the batheSelf() method because it only exists for Cat. That leads me to believe that I should only declare from an Interface if I am only going to use methods declared in the Interface (and not extra methods from the subclass), otherwise I should declare from the Class directly (in this case Cat). Am I correct in this assumption?
When there is a choice between referring to an object by their interface or a class, the former should be preferred, but only if an appropriate type exists.
Consider StringimplementsCharSequence as an example. You should not just blindly use CharSequence in preferrence to String for all cases, because that would deny you simple operations like trim(), toUpperCase(), etc.
However, a method that takes a String only to care about its sequence of char values should use CharSequence instead, because that is the appropriate type in this case. This is in fact the case with replace(CharSequence target, CharSequence replacement) in the String class.
Another example is java.util.regex.Pattern and its Matcher matcher(CharSequence) method. This lets a Matcher be created from Pattern for not just String, but also for all other CharSequence there are out there.
A great example in the library of where an interface should've been used, but unfortunately wasn't, can also be found in Matcher: its appendReplacement and appendTail methods accept only StringBuffer. This class has largely been replaced by its faster cousin StringBuilder since 1.5.
A StringBuilder is not a StringBuffer, so we can not use the former with the append… methods in Matcher. However, both of them implementsAppendable (also introduced in 1.5). Ideally Matcher's append… method should accept any Appendable, and we would then be able to use StringBuilder, as well as all other Appendable available!
So we can see how when an appropriate type exists referring to objects by their interfaces can be a powerful abstraction, but only if those types exist. If the type does not exist, then you may consider defining one of your own if it makes sense. In this Cat example, you may define interface SelfBathable, for example. Then instead of referring to a Cat, you can accept any SelfBathable object (e.g. a Parakeet)
If it does not make sense to create a new type, then by all means you can refer to it by its class.
See also
Effective Java 2nd Edition, Item 52: Refer to objects by their interfaces
If appropriate interface types exist, then parameters, return values, and fields should all be declared using interface types. If you get into the habit of using interface types, your program will be much more flexible. It is entirely appropriate to refer to an object by a class if no appropriate interface exists.
Related links
Bug ID: 5066679 - java.util.regex.Matcher should make more use of Appendable
Yes, you are correct. You should declare as the most general type providing the methods you use.
This is the concept of polymorphism.
Your are correct, but you can cast from the interface to the desired pet if you need. For example:
PetInterface p = new Cat();
((Cat)p).batheSelf();
Of course if you try to cast your pet to a dog you cannot call the batheSelf() method. It would not even compile. So, to avoid problems, you could have a method like this:
public void bathe(PetInterface p){
if (p instanceof Cat) {
Cat c = (Cat) p;
c.batheSelf();
}
}
When using instanceof, you make sure you will not try to make a dog bathe himself during runtime. Which would throw an error.
Yes, you are correct. By having Cat implent "PetInterface" you can use it in the example above and easily add more kinds of pets. If you really need to be Cat-specific you need to access the Cat class.
You can call method batheSelf from talk in Cat.
Generally, you should prefer interfaces to concrete classes. Along those lines, if you can avoid using the new operator (which always requires a concrete type as in your new ArrayList example), even better.
This all has to do with managing dependencies in your code. It's best to depend only on highly abstract things (like interfaces) because they also tend to be very stable (see http://objectmentor.com/resources/articles/stability.pdf). Because they have no code, they only must be changed when the API changes...in other words, when you want that interface to present a different behavior to the world, i.e., a design change.
Classes, on the other hand, change all the time. Code that depends upon a class doesn't care how it does what it does, as long as the inputs and the outputs of the API don't change, callers shouldn't care.
You should strive to nail down the behavior of your classes according to the Open-Closed Principle (see http://objectmentor.com/resources/articles/ocp.pdf), that way existing interfaces need not change even when you add functionality, you can just specify a new subinterface.
The old way of avoiding the new operator was by using the Abstract Factory pattern, but that comes with its own set of problems. Better is to use a tool like Guice that does dependency injection, and prefer constructor injection. Make sure you understand the Dependency Inversion Principle (see http://objectmentor.com/resources/articles/dip.pdf) before you start using dependency injection. I've seen a lot of people inject inappropriate dependencies and then later complain that the tool isn't helping them...it won't make you a great programmer, you still have to use it appropriately.
Example: you are writing a program that helps students learn physics. In this program, students can put a ball in various physical scenarios and watch how it behaves: shoot it out of a cannon off a cliff, put it underwater, in deep space, etc. Question: you want to include something about the heaviness of the ball in the Ball API...should you include a getMass() method or a getWeight() method?
Weight depends upon the environment the ball happens to be in. It might be convenient for callers to be able to call one method and get the weight of the ball wherever it happens to be, but how do you write this method? Each ball instance must constantly keep track of where it is and what the current gravitational constant is. So you should prefer getMass(), because mass is an intrinsic property of the ball and doesn't depend on its environment.
Wait, what if you just use getWeight(Environment) instead? This way, the ball instance can just get its current g out of the environment and proceed...better yet, you can use Guice to inject the Environment in the Ball's constructor! This is the type of misuse I often see, and people end up blaming Guice for not being able to handle dependency injection as seamlessly as they would've hoped.
The problem is not Guice here, it's the Ball API design. Weight is not an intrinsic property of the ball, so it's not a property that should be accessible from the ball. Instead, Ball should implement the MassiveObject interface with a getMass() method, and Environment should have a method called getWeightOf(MassiveObject). Intrinsic to the Environment is its own gravitational constant, so this is much better. And Environment only depends upon a simple interface now, MassiveObject...but it's job is to contain objects, so this is as it should be.
Why not simply do this!
Cat c = new Cat();
PetInterface p = (PetInterface)c;
p.talk();
c.batheSelf();
Now we have a single object, which can be manipulated using 2 references.
The reference p can be used to call functions defined in interface and c can be used to call functions defined in class(or superclass) only.