last weekend i read some stuff about interfaces, abstract classes and design principles. At the end i got a bit confused and i tried to build an example of what i learned (or thought i had learned).
Here is my example:
The case would be to model a class that holds informations about trees.
First of all i would make an interface:
public interface Tree{
public void grow();
}
The interface holds all methods that should be implemented by the concrete trees. So far so good but such a tree needs some attributes (variables) that are shared over all tree families. For that purpose i would use a abstract class:
public abstract class AbstractTree implements Tree {
private String barColor;
private int maxHeight;
private boolean isEvergreen;
}
Is this the right way or am i not able to make a kind of contract about attributes (variables) that should be in the other classes?
After the attribute part is done i would like to have 3 type of trees.
Oak
Maple
Spruce
So each of these tree "tpyes" can have individual variables.
public class OakTreeImpl extends AbstractTree{
private String barColor;
private int maxHeight;
private boolean isEvergreen;
private String foo;
#Override
public void grow() {
}
}
Does this approach sound right in an object-oriented design principles way or am i totally wrong with it?
This does work, however it does not make much sense, since the interface is totally obsolete in this case.
You should add the grow method to your AbstractTree like this:
public abstract class AbstractTree{
protected String barColor;
protected int maxHeight;
protected boolean isEvergreen;
public abstract void grow();
}
Using an interface would make sense, if you wanted to have different kinds of plants that should all be able to grow for instance.
interface Plant{
void grow();
}
abstract class Tree implements Plant{
void grow(){ /* do sth */ }
}
abstract class Flower implements Plant{
void grow(){ /* do sth totally different */
}
The purpose of an interface is to provide the same method in multiple classes with different implementations, whereas an abstract class provides methods and attributes that are shared in all of their child classes.
If a method in an abstract class is also abstract, every child class must implement it themselves.
I would rather mark the instance variables as protected.
Because all protected members of a super class is accessible to child classes. If and only if, parent and child classes are in the same package
public abstract class AbstractTree implements Tree {
protected String barColor;
protected int maxHeight;
protected boolean isEvergreen;
}
public class OakTreeImpl extends AbstractTree{
// I can access barColor, maxHeight, isEvergreen in this class
#Override
public void grow() {
}
}
Although this may partially be subjective, I have to concur with the other answers given so far.
The Tree interface is NOT obsolete. When you want to model a Tree, then there should be a Tree interface, clearly stating the methods that every Tree has.
Particularly, I'd advice against the recommendation to simply replace it with the AbstractTree class. Some people say that you should hardly use abstract classes at all (e.g. Jaroslav Tulach in "Practical API Design"). I'd at least say that you should use them very conservatively. Most importantly: You should try to avoid letting appear abstract classes in the public interface of other classes. For example, if you had another class/interface, with a method like
void makeGrow(Tree tree) {
System.out.println("Growing "+tree);
tree.grow();
}
then replacing this appearance of Tree to AbstractTree will decrease flexibility. You will never be able to use a class that does not inherit from AbstractTree - and considering that you can only inherit from one class, this may be a severe limitation. (You can always implement multiple interfaces - so an interface does not limit the flexibility here).
But even if you use an abstract based class, I'd recommend to use protected fields conservatively. Or, more generally, be aware of the implications of inheriting from a class, as described in "Item 17 - Design and document for inheritance or else prohibit it" of "Effective Java" by Joshua Bloch.
In many cases, you don't want the inheriting class to have full access to the fields. So you should at least consider making the fields private, and only offer protected methods for the kind of access that you want to grant to inheriting classes.
public interface Tree{
public void grow();
}
abstract class AbstractTree implements Tree {
// Do the values of these fields ever change? If not,
// then make them final, and set them only in the
// constructor
private final String barColor;
private final int maxHeight;
private final boolean evergreen;
protected AbstractTree(...) { ... }
// Subclasses are only allowed to read (but not write) these fields
protected final String getBarColor() { return barColor; }
protected final intgetMaxHeight() { return maxHeight; }
protected final boolean isEvergreen() { return evergreen; }
}
Related
Disclaimer: I know there are a lot of questions about polymorphism out there, but I couldn't find a suitable answer for my problem. If your Google-fu is better than mine, please forgive the dupe.
I have a model using inheritance, such as in the example below.
public abstract class Base {
// ...
}
public class ConcreteA extends Base {
private String someString;
// ...
}
public class ConcreteB extends Base {
private boolean someBool;
// ...
}
And I also have a List<Base>, which is composed of objects that are either ConcreteAs or ConcreteBs.
I need to generate a graphical view for each object in the list, but the resulting element is not the same for ConcreteAs and ConcreteBs. From the example above, the view for ConcreteA would be a text field, while the view for a ConcreteB would be a check box.
How can I achieve this using OO principles?
The problem that you have is that you somewhere return a List<Base> when the caller must know the concrete type.
Usually this is caused because one tried to make a method more generic. E.g. if someone has this service methods
public List<ConcreteA> doSomethingA(){ ... }
public List<ConcreteB> doSomethingB(){ ... }
he might think it is a better idea to introduce a superclass, Base so that both methods can be substituted by
public List<Base> doSomething(){ ... }
This is a good idea if the caller is only interessted in a Base object. This means that ConcreateA and ConcreteB have some common behavior that the caller only depends on.
But in your case it seems that the caller needs the concrete type information that is not available anymore, because of the more generic method.
So you either must preserve or reconstruct the type information.
Preserve the type by using a custom return type instead of making the method generic
public class Result {
private List<ConcreteA> concreteA;
private List<ConcreteB> concreteA;
}
public Result doSomething();
Recunstruct the type information using instanceof
Reconstruct the type information by introcucing a visitor pattern.
Not a pattern - this is what abstraction is all about. Declare a method you want all subclasses of Base to implement and each must implement it in their own way.
Obviously you would pass parameters and/or get results of the methods.
public abstract class Base {
abstract void graphicalView();
}
public class ConcreteA extends Base {
#Override
void graphicalView() {
}
}
public class ConcreteB extends Base {
#Override
void graphicalView() {
}
}
public void test() throws IOException {
List<Base> bases = new ArrayList<>();
for ( Base b : bases ) {
b.graphicalView();
}
}
I think you're looking for Visitor Design Pattern.
From Wikipedia :
In object-oriented programming and software engineering, the visitor
design pattern is a way of separating an algorithm from an object
structure on which it operates. A practical result of this separation
is the ability to add new operations to extant object structures
without modifying the structures. It is one way to follow the
open/closed principle.
In essence, the visitor allows adding new virtual functions to a
family of classes, without modifying the classes. Instead, a visitor
class is created that implements all of the appropriate
specializations of the virtual function. The visitor takes the
instance reference as input, and implements the goal through double
dispatch.
In such cases, I usually use generics something like this
public abstract class Base <T extends Shape>{
public abstract T drawShape();
}
public class ConcreatA extends Base<Circle> {
#Override
public Circle drawShape() {
return null;
}
}
public class ConcreatB extends Base<Square> {
#Override
public Square drawShape() {
return null;
}
}
So now you can use list of Shapes
Today, our team has the problem.
There is a class AClass that implements the interface AInterface. To date, we need to introduce a new entity(BClass) that would use only part of the interface A.
The first thing about which we think - split interface AInterface into 2 components (composition)
The problem is that the logic AClass->AInterface - is a model prom pattern MVC. And we extremely do not want to cut it into several interfaces.
We know that Java provides a mechanism for inheritance to extend a class or interface.
But is there any way to constrict the implementation? Or maybe exist another way?
Note : we doesn't want use UnsupportedMethodException. Our goal - clean API.
Update :
Next solution - not for us.
GOAL :
Put your restricted subset into one interface, and have the larger interface extend it. Then have A implement the child (larger) interface, and B implement the parent (smaller) one. Then both A and B implement the smaller interface, while only A implements the larger. Use the smaller interface for coding to whenever you can.
public interface AInterface {
void add();
void remove();
}
public interface ASubInterface extends AInterface {
void invalidate();
void move();
}
public class AClass implements ASubInterface { /* 4 methods */ }
public class BClass implements AInterface { /* 2 methods */ }
The very fact that you have a usecase which only requires half of the methods exposed in the original interface tells you that you can further break that interface down. If you think about the design - how do your objects behave in your usecase scenarios, will tell you how it should be designed.
Just by looking at the names of the methods you have given, I'd expect them to be 2 different interfaces where AClass implements both the interfaces while BClass only implements the second interface.
You cannot "disable" polymorphism in certain cases, it's a major feature of the Java language.
If BClass shouldn't have those methods, then it shouldn't implent the interface.
AClass does more than BClass, so it should be another type. Why would you want them to be interchangeable?
On another note, many libraries use UnsupportedMethodException (like even the Java SDK with List collections). It just needs to be documented properly. So if you need ro use that to achieve your goal, go for it.
Your needs seem a little strict but perhaps a abstract class could help.
public interface AInterface {
public void add();
public void remove();
public void invalidate();
public void move();
}
public abstract class BBase implements AInterface {
#Override
public abstract void add();
#Override
public abstract void remove();
#Override
public void invalidate() {};
#Override
public void move() {};
}
public class BClass extends BBase {
#Override
public void add() {
}
#Override
public void remove() {
}
}
Here I create a BBase which stubs out the two methods you want removed but leaves the other two abstract. BClass demonstrates how it would be used.
You can do this if you compile AClass and BClass separately. I.e. compile AClass with the full version of the interface, then modify the interface (remove the methods) and compile BClass with this modified version of the interface.
P.S. By no means this is a painless approach.
I have a series of classes, A,B,C... (several dozen in total) that share common code. There can be many instance of each class A,B,C... . I'm planning to create a superclass, Abstract, that will contain that code instead.
Problem is, the common stuff works on an object that is unique on a per-class (not per-instance) basis. This is currently solved by A,B,C... each having a static field with the corresponding value. Obviously, when I refactor the functionality into Abstract, this needs to be changed into something else.
In practice, it currently looks like this (note that the actual type is not String, this is just for demonstrative purposes) :
public class A implements CommonInterface {
private static final String specificVar = "A";
#Override
public void common() {
specificVar.contains('');
}
}
public class B implements CommonInterface {
private static final String specificVar = "B";
#Override
public void common() {
specificVar.contains('');
}
}
The best idea I've come up with until now is to have a Map<Class<? extends Abstract>,K> (where K is the relevant type) static field in Abstract, and A,B,C... each containing a static initalization block that places the relevant value into the map. However, I'm not convinced this is the best that can be done.
Note that I'm not using any DI framework.
So, what would be the most concise, in terms of code contained in the subclasses, way to refactor the static fields in A,B,C... handled by the common code, without sacrificing field access efficiency?
Perhaps an enum is what you want.
enum MyInstances implements MyInterface {
A {
fields and methods for A
}, B {
fields and methods for B
};
common fields for all MyInstances
common methods for all MyInstances
}
// To lookup an instance
MyInstances mi = MyInstances.valueOf("A");
As you haven't shown any source code, we can't really tell if the use of static fields is a good or a bad design choice.
Considering the use of static fields by the subclasses is indeed a good design choice, the first way of having common code in a superclass to access them is by calling abstract methods that would be implemented in the subclasses.
Example:
public abstract class SuperClass {
public void processCommonLogic() {
// Common logic
// Execute specific logic in subclasses
processSpecificLogic();
}
public abstract void processCommonLogic();
}
public class ASubClass extends SuperClass {
public static int SPECIFIC_SUBCLASS_CONSTANT = 0;
public void processSpecificLogic() {
// Specific subclass logic
doSomethingWith(ASubClass.SPECIFIC_SUBCLASS_CONSTANT);
}
}
You could use the Template Method Pattern.
Have an abstract method getValue() defined in your abstract class and used within your abstract class wherever you require the value. Then each of your subclasses simply need to implement the getValue method and return the correct value for that subclass.
We can access the Super Class methods which consists of operations on private data members and print the results.But why can't I print the private data members of Super Class with the SubClass object calling them in my main function? Someone please explain me.
Here is the example below.
class SuperClass1
{
private int a;
private int b;
SuperClass1(int p,int q)
{
a=p;
b=q;
}
SuperClass1(SuperClass1 obj)
{
a=obj.a;
b=obj.b;
}
SuperClass1()
{
a=-1;
b=-1;
}
int Vol()
{
return a*b;
}
}
class SubClass1 extends SuperClass1
{
int c;
SubClass1(int p,int q,int r)
{
super(p,q);
c=r;
}
SubClass1(SubClass1 obj)
{
super(obj);
c=obj.c;
}
SubClass1()
{
super();
c=-1;
}
}
public class Super
{
public static void main(String[] args)
{
SubClass1 obj1=new SubClass1();
//System.out.println("The values of obj1 are:"+obj1.a+""+obj1.b+""+obj1.c);
int vol=obj1.Vol();
System.out.println("The volume is :"+vol);
}
}
security and encapsulation
The superclass is letting its subclasses use only the public and protected methods/fields.
This allows the designer of the superclass to change the implementation of these methods if he sees it better, without breaking the subclass's correctness.
A text book example is a complex number class.
The programmer using this class only needs its functionality, he doesn't care if the implementation is with imaginary and real fields or with radius and theta fields [two distinct ways to represent complex number].
It allows the designer of the ComplexNumber class more freedom if he wants to change the class in later versions, and it also allows the user less worries: he doesn't need to take care for all the details, some are being taken care of for him.
Bonus: note you can break this behavior and access private fields and methods by using reflection - but when you do so - all bets are off, and you do it on your own responsibility.
Your question isn't very clear without an example, but I suspect that the "methods which consist of operations on private data members" aren't private. It doesn't matter that they work by accessing private data - they're not private themselves. It would be pretty pointless having access modifiers if public methods could only access other public members etc.
The whole point of encapsulation is that only the class itself should care about implementation details such as the fields in question, but can expose a contract in terms of its public (and protected) API. Code outside the class shouldn't care about the private implementation details.
JLS says:
Members of a class that are declared private are not inherited by
subclasses of that class. Only members of a class that are declared
protected or public are inherited by subclasses declared in a package
other than the one in which the class is declared.
So, to answer you question. No, private members are not accessible by subclasses.
Private members are not inherited; only the protected and public members are.
If possible, you can do one of the following:
Make the private properties of the superclass protected
Make public getters (and setters if needed) for the private properties
Why do we need constructors and private members in the abstract class? It is not like we are ever going to create an instance of that class.
You will create instances, just instances of a derived class. Those derived classes will still need to call constructors, and can still call members of the abstract class - which may in turn use private members.
Here's an example (not a terribly useful one, but just to show the basic idea...)
public abstract class NamedObject
{
private final String name = name;
protected NamedObject(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
public class Computer extends NamedObject
{
private final int processorSpeed;
public Computer(String name, int processorSpeed)
{
super(name); // See, the constructor is useful
this.processorSpeed = processorSpeed;
}
public String toString()
{
return getName() + " (" + processorSpeed + ")";
}
}
I can't say I write abstract classes that often, generally preferring composition to inheritance, but when I do create them I certainly use constructors and private members.
Abstract classes provide a partial implementation of some interface. It's perfectly reasonable to consider that you might want to provide part of that implementation and disallow client code (concrete subclasses) from accessing the specifics - i.e. an extension of the principle of encapsulation.
Marking some members as private forces the inheriting class to call protected methods to access that partial implementation; providing a constructor allows for subclasses to initialise the parent's encapsulated state during their own construction.
Unlike an interface, an abstract class that defines data fields is in fact instantiated in the sense that these data fields are allocated. It is just that they are never instantiated on their own, they are instantiated as part of something bigger - the subclass. So when the subclass is built, the supertype is built as well, which is why you would need a constructor.
Depending on your hierarchy, your abstract class may have a meaning and state. For example, if your application is a school you may have the notion of a person (that has a name and an SSN), but you would have different subtypes for students and for faculty. Because both types of people share certain state structure (name and SSN) you would have both classes extend the Person class. But you would never simply instantiate a person directly.
In addition to Jon's answer, I'd like to mention that abstract classes still go well with composition, if you keep the subclass tree shallow. I.e. it is great for providing a common base class for a few closely related objects, but not for creating a gigantic tree of subclasses.
Why do you need private class? I think that you are confusing abstract classes with interfaces. Unlike interfaces, abstract classes can hold functionality. For example:
public class AbstractBase{
private int num;
public AbstractBase(int number){
this->num = number;
}
public int method(){
return ( this->num * this->templateMethod());
}
public abstract int templateMethod();
}
public class ConcreteDerived extends AbstractBase{
public ConcreteDerived(){
super(4);
}
public int templateMethod(){
return number; //number is the result of some calculation
}
}
In this example, you´ll never explicitly instantiate AbstractBase, but by declaring members and constructors, you can customize the functionality of your classes (this is called template method).
Assuming you're doing ad hoc code or prototyping, you do instantiate abstract classes (or maybe even interfaces) from time to time. They're called anonymous inner classes (one, two) and look like this:
// you have this...
public abstract class SomeClass {
public abstract String returnAString();
}
// ...and this...
public class OtherClass {
public void operate(SomeClass c) {
System.out.println(c.returnAString());
}
}
// ...so you do this:
OtherClass oc = new OtherClass();
// this is one of the reasons why you need to specify a constructor
oc.operate(new SomeClass() {
#Override
public String returnAString() {
return "I'm an anonymous inner class!";
}
});
This example is of course quite redundant but should expose the point. Some existing frameworks even rely on the heavy usage of this behaviour, namely Apache Wicket at least.