General OO question about inheritance and extensibility - java

So, in a single parent inheritance model what's the best solution for making code extensible for future changes while keeping the same interface (I'd like to emphasize the fact that these changes cannot be known at the time of the original implementation, the main focus of my question is to explore the best mechanism/pattern for supporting these changes as they come up)? I know that this is a very basic OO question and below I provide example of how I've been going about it, but I was wondering if there a better solution to this common problem.
Here's what I've been doing (the example code is in Java):
In the beginning, the following two classes and interface are created:
public class Foo
{
protected int z;
}
public interface FooHandler
{
void handleFoo(Foo foo);
}
public class DefaultFooHandler implements FooHandler
{
#Override
public void handleFoo(Foo foo)
{
//do something here
}
}
The system uses variables/fields of type FooHandler only and that object (in this case DefaultFooHandler) is created in a few, well-defined places (perhaps there's a FooHandlerFactory) so as to compensate for any changes that might happen in the future.
Then, at some point in the future a need to extend Foo arises to add some functionality. So, two new classes are created:
public class ImprovedFoo extends Foo
{
protected double k;
}
public class ImprovedFooHandler extends DefaultFooHandler
{
#Override
public void handleFoo(Foo foo)
{
if(foo instanceof ImprovedFoo)
{
handleImprovedFoo((ImprovedFoo)foo);
return;
}
if(foo instanceof Foo)
{
super.handleFoo(foo);
return;
}
}
public void handleImprovedFoo(ImprovedFoo foo)
{
//do something involving ImprovedFoo
}
}
The thing that makes me cringe in the example above is the if-statements that appear in ImprovedFooHandler.handleFoo
Is there a way to avoid using the if-statements and the instanceof operator?

First of all the code you wrote won't work.
Each time you see instanceof and if...else together be very careful. The order of these checks is very important. In your case you'll never execute handleImpovedFoo. Guess why :)
It's absolutely normal you have these instanceof statements. Sometimes it's the only way to provide different behavior for a subtype.
But here you can use another trick: use simple Map. Map classes of foo-hierarchy to instances of fooHandler-hierarchy.
Map<Class<? extends Foo>, FooHandler> map ...
map.put( Foo.class, new FooHandler() );
map.put( ImprovedFoo.class, new ImprovedFooHandler() );
Foo foo ...; // here comes an unknown foo
map.get( foo.getClass() ).handleFoo( foo );

The best way of handling this depends too much on the individual case to provide a general solution. So I'm going to provide a number of examples and how I would solve them.
Case 1: Virtual File System
Clients of your code implement virtual file systems which enable them to operate any sort of resource which can be made to look like a file. They do so by implementing the following interface.
interface IFolder
{
IFolder subFolder(String Name);
void delete(String filename);
void removeFolder(); // must be empty
IFile openFile(String Name);
List<String> getFiles();
}
In the next version of your software you want to add the ability to remove a directory and all it contents. Call it removeTree. You cannot simply add removeTree to IFolder because that will break all users of IFolder. Instead:
interface IFolder2 implements IFolder
{
void removeTree();
}
Whenever a client registers an IFolder (rather then IFolder2), register
new IFolder2Adapter(folder)
Instead, and use IFolder2 throughout your application. Most of your code should not be concerned with the difference about what old versions of IFolder supported.
Case 2: Better Strings
You have a string class which supports various functionality.
class String
{
String substring(int start, end);
}
You decide to add string searching, in a new version and thus implement:
class SearchableString extends String
{
int find(String);
}
That's just silly, SearchableString should be merged into String.
Case 3: Shapes
You have a shape simulation, which lets you get the areas of shapes.
class Shape
{
double Area();
static List<Shape> allShapes; // forgive evil staticness
}
Now you introduce a new kind of Shape:
class DrawableShape extends Shape
{
void Draw(Painter paint);
}
We could add a default empty Draw method to Shape. But it seems incorrect to have Shape have a Draw method because shapes in general aren't intended to be drawn. The drawing really needs a list of DrawableShapes not the list of Shapes that is provided. In fact, it may be that DrawableShape shouldn't be a Shape at all.
Case 4: Parts
Suppose that we have a Car:
class Car
{
Motor getMotor();
Wheels getWheels();
}
void maintain(Car car)
{
car.getMotor().changeOil();
car.getWheels().rotate();
}
Of course, you know somewhere down the road, somebody will make a better car.
class BetterCar extends Car
{
Highbeams getHighBeams();
}
Here we can make use of the visitor pattern.
void maintain(Car car)
{
car.visit( new Maintainer() );
}
The car passes all of its component parts to calls into ICarVisitor interface allowing the Maintainer class to maintain each component.
Case 5: Game Objects
We have a game with a variety of objects which can be seen on screen
class GameObject
{
void Draw(Painter painter);
void Destroy();
void Move(Point point);
}
Some of our game objects need the ability to perform logic on a regular interval, so we create:
class LogicGameObject extends GameObject
{
void Logic();
}
How do we call Logic() on all of the LogicGameObjects? In this case, adding an empty Logic() method to GameObject seems like the best option. Its perfectly within the job description of a GameObject to expect it to be able to know what to do for a Logic update even if its nothing.
Conclusion
The best way of handling this situations depends on the individual situation. That's why I posed the question of why you didn't want to add the functionality to Foo. The best way of extending Foo depends on what exactly you are doing. What are you seeing with the instanceof/if showing up is a symptom that you haven't extended the object in the best way.

In situations like this I usually use a factory to get the appropriate FooHandler for the type of Foo that I have. In this case there would still be a set of ifs but they would be in the factory not the implementation of the handler.

Yes, don't violate LSP which is what you appear to be doing here. Have you considered the Strategy pattern?

This looks like a plain simple case for basic polymorphism.Give Foo a method named something like DontWorryI'llHandleThisMyself() (um, except without the apostrophe, and a more sensible name). The FooHandler just calls this method of whatever Foo it's given. Derived classes of Foo override this method as they please. The example in the question seems to have things inside-out.

With the visitor pattern you could do something like this,
abstract class absFoo {}
class Foo extends absFoo
{
protected int z;
}
class ImprovedFoo extends absFoo
{
protected double k;
}
interface FooHandler {
void accept(IFooVisitor visitor, absFoo foo);
}
class DefaultFooHandler implements FooHandler
{
public void accept(IFooVisitor visitor, absFoo foo)
{
visitor.visit(this, foo);
}
public void handleFoo(absFoo foo) {
System.out.println("DefaultFooHandler");
}
}
class ImprovedFooHandler implements FooHandler
{
public void handleFoo(absFoo foo)
{
System.out.println("ImprovedFooHandler");
}
public void accept(IFooVisitor visitor, absFoo foo) {
visitor.visit(this, foo);
}
}
interface IFooVisitor {
public void visit(DefaultFooHandler fooHandler, absFoo foo);
public void visit(ImprovedFooHandler fooHandler, absFoo foo);
}
class FooVisitor implements IFooVisitor{
public void visit(DefaultFooHandler fHandler, absFoo foo) {
fHandler.handleFoo(foo);
}
public void visit(ImprovedFooHandler iFhandler, absFoo foo) {
iFhandler.handleFoo(foo);
}
}
public class Visitor {
public static void main(String args[]) {
absFoo df = new Foo();
absFoo idf = new ImprovedFoo();
FooHandler handler = new ImprovedFooHandler();
IFooVisitor visitor = new FooVisitor();
handler.accept(visitor, idf);
}
}
But this does not guarantee only Foo can be passed to DefaultFooHandler. It allows ImprovedFoo also can be passed to DefaultFooHandler. To overcome, something similar can be done
class Foo
{
protected int z;
}
class ImprovedFoo
{
protected double k;
}
interface FooHandler {
void accept(IFooVisitor visitor);
}
class DefaultFooHandler implements FooHandler
{
private Foo iFoo;
public DefaultFooHandler(Foo foo) {
this.iFoo = foo;
}
public void accept(IFooVisitor visitor)
{
visitor.visit(this);
}
public void handleFoo() {
System.out.println("DefaultFooHandler");
}
}
class ImprovedFooHandler implements FooHandler
{
private ImprovedFoo iFoo;
public ImprovedFooHandler(ImprovedFoo iFoo) {
this.iFoo = iFoo;
}
public void handleFoo()
{
System.out.println("ImprovedFooHandler");
}
public void accept(IFooVisitor visitor) {
visitor.visit(this);
}
}
interface IFooVisitor {
public void visit(DefaultFooHandler fooHandler);
public void visit(ImprovedFooHandler fooHandler);
}
class FooVisitor implements IFooVisitor{
public void visit(DefaultFooHandler fHandler) {
fHandler.handleFoo();
}
public void visit(ImprovedFooHandler iFhandler) {
iFhandler.handleFoo();
}
}
public class Visitor {
public static void main(String args[]) {
FooHandler handler = new DefaultFooHandler(new Foo());
FooHandler handler2 = new ImprovedFooHandler(new ImprovedFoo());
IFooVisitor visitor = new FooVisitor();
handler.accept(visitor);
handler2.accept(visitor);
}
}

Related

How to avoid stackoverflow while calling methods of two classes in eachother Java

I searched the whole StackOverflow website I come across only one nearest
answer but not working in my condition.
How can I call methods of two classes in each other
First Class is Alpha and calling a Function of Beta
public Class Alpha
{
Beta obj;
public Alpha()
{
obj = new Beta();
}
public void A()
{
print A;
obj.B();
}
}
Second Class is Beta and calling a function of Alpha
public Class Beta
{
Alpha obj;
public Beta()
{
obj = new Alpha();
}
public void B()
{
print B;
obj.A()
}
}
In Java/android, it shows StackOverflow exception. Due to the recursive call of constructors of each other.
How to avoid this Exception?
I have 15 Classes and each one is linked Cyclically.
Do I need to use parent class?
Or How I should use constructors to avoid StackOverflow Exception?
Here's a suggestion that will break the cycle: Specify one class as the parent and the other as the dependent.
Let's put Alpha in charge:
public class Alpha {
private Beta beta;
public Alpha() {
this.beta = new Beta(this);
}
}
Here's the child Beta:
public class Beta {
private Alpha alpha;
public Beta(Alpha parent) {
this.alpha = parent;
}
}
No more cycle.
You shall change your class Beta's definition to break the circular link between the two classes and creating their instances. It could be somewhat like this instead:
public class Beta {
Alpha obj;
public Beta() {
}
public void B() {
print B;
new Alpha().A();
}
}
Ideally, you shall not create instances of other classes unless you would want to access them.
The stack overflow is obvious; it's not just that the class definitions are cyclical; the constructors are recursive. The recursion is just "hidden" because they are in different classes. With any recursion, there must be some limit condition to break the recursion cycle. Without knowing the details of your problem -- why do you have this cyclical definition -- it's hard to give a solution. It really comes down to a question of code architecture. I can offer a few suggestions.
First, I generally dislike cyclical definitions. It leads to confusion and issues in doing code builds and ports. This can be avoided by using interfaces; maybe an empty marker interface. I would then take assignment of the internal objects out of the constructor, and make an explicit set() function, so that the caller has to initialize these:
public interface SomeInterface { }
public class Alpha implements SomeInterface
{
private SomeInterface obj;
public Alpha()
{}
public void setBeta (SomeInterface si)
{
obj = si;
}
}
public class Beta implements SomeInterface
{
private SomeInterface obj;
public Beta ()
{ }
public void setAlpha ( SomeInterface si )
{
obj = si;
}
}
In the calling code, you would have
Alpha a = new Alpha();
a.setBeta ( new Beta() );

Java inheritance and method resolution order

I've got the following code example:
class p {
public void druckauftrag() {
// ...
drucke();
}
public void drucke() {
System.out.println("B/W-Printer");
}
}
class cp extends p {
public void drucke() {
System.out.println("Color-Printer");
}
}
Calling the following lines:
cp colorprinter = new cp();
cp.druckauftrag();
There is no problem understanding why "cp.druckauftrag();" results in console output "Color-Printer".
But when I call:
p drucker = (p)colorprinter;
drucker.druckauftrag();
I get the same output - why?
Does the typecast overwrite the object "drucker" 's method "drucke" with "drucke" from colorprinter?
Thanks in advance for every explanation.
colorprinter does not stop being an instance of cp when you use the cast operator on it, so its implementation of public void drucke() does not change
What you are expressing with your (p)colorprinter casting is the kind of contract (interface) you expect the object colorprinter to satisfy, which includes a public method with the signature public void drucke(), but not any specific implementation.
And, by the way, this casting is already performed implicitly when you declare drucker of the type p, so (p) is redundant in p drucker = (p)colorprinter;. p drucker = colorprinter; will suffice.
Here you can learn more about typecasting.
Keep in mind that it's best practice to extend from abstract classes or interfaces and only #Override (implement) abstract methods. A better design of your code would be:
abstract class BasePrinter {
public void druckauftrag() {
// ...
drucke();
}
public void drucke();
}
class p extends BasePrinter {
public void drucke() {
System.out.println("B/W-Printer");
}
}
class cp extends BasePrinter {
public void drucke() {
System.out.println("Color-Printer");
}
}
But of course constraints don't always allow for that kind of redesign. Passing the base requirements as parameters to the constructor (dependency injection) instead of extending a base class can also be a good alternative:
interface Druckable {
void drucke();
}
class Druckauftrager {
Druckable dk;
Druckauftrager(Drukable dk){
this.dk = dk;
}
public void druckauftrag() {
// ...
dk.drucke();
}
}
class p implements Druckable {
public void drucke() {
System.out.println("B/W-Printer");
}
}
class cp implements Druckable {
public void drucke() {
System.out.println("Color-Printer");
}
}
Now, if you want to express that a printer requires or can have multiple printing capabilities (like both color and b/w), you just write the class with as much extra Drukable properties and constructor parameters as you want, for example:
class BlackAndWhiteOrColorPrinter {
p blackAndWhitePrintService;
cp colorPrintService;
Druckable selectedPrintService;
BlackAndWhiteOrColorPrinter (p blackAndWhitePrintService, cp colorPrintService){
this.blackAndWhitePrintService = blackAndWhitePrintService;
this.colorPrintService = colorPrintService;
this.selectedPrintService = blackAndWhitePrintService;
}
public void druckauftrag() {
// ...
selectedPrintService.drucke();
}
}
This way, you can even write a class MultiPrinter with a MultiPrinter(List<Druckable> printServices) constructor and add any number of printing modes to its list of printing services: p, cp, and whatever other implementation of Druckable with its public void drucke() comes in the future. It is also extra practical if you want to introduce unit testing, so you can provide mockup objects that force the particular conditions you want to test, like druke() throwing a PaperJamException, for example.
For more information on how interfaces, overriding and inheritance work, see https://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.html
BTW, acording to the latest revision of the official java code conventions guide and also by de facto standard, classes in Java should use CamelCase naming convention. You can also benefit greatly from using semanting naming on all your definitions, like BlackAndWhitePrinter blackAndWhitePrinter and ColorPrinter colorPrinter.
colorprinter is an instance of cp. Even when you upcast it to p, it's drucke() method will be still the one from cp.
The difference is that after you upcast colorprinter, you will not be able to invoke the methods that cp defines on its own.
When you create an object using new operator, memory is allocated in heap. Methods and fields are actually there depending upon the concrete actual class of the object.
Alter a sub class overrides and modifies a behavior from its super class, invoking the overridden method will always result in the modified behavior. Casting will only mean that the object of sub class is now represented by the super type as the object has a modified behavior for a method will always result in the modified behavior.
Suppose you have below classes
public class Fruit{
public void taste(){
System.out.println("depends upon the actual fruit");
}
}
public class Mango extends Fruit{
#Override
public void taste(){
System.out.println("sweet");
}
public void wayToExposeSuperMethod(){
super.taste();
}
}
In other words its like calling mango as a fruit but still mango remains mango.
For above code
Fruit fruit = new Mango();
fruit.taste(); // <-- this will output : sweet
((Mango)fruit).taste();// <-- this will output : sweet
fruit.wayToExposeSuperMethod(); // <-- this will not compile
((Mango)fruit).wayToExposeSuperMethod(); // <-- this will output : depends upon the actual fruit

Java Passing in Type as Function Parameter

I come from a Python background and in Python you can pass in the type of an object as a parameter. But in Java you cannot do this, any tips on how to get something like this working?
private void function(Type TypeGoesHere)
Stock s = new TypeGoesHere();
s.analyze();
}
Java does not support Python’s way of referencing functions and classes. To achieve this behaviour, you have to use two advanced techniques: generics and reflection. Explaining these concepts is beyond the scope of a SO answer. You should read a Java guide to learn about them.
Yet here is an example how this would look like, assuming that the given class has a no-argument constructor:
public <T extends Stock> void analyzeNewStock(Class<T> clazz) throws Exception {
Stock s = clazz.newInstance();
s.analyze();
}
Then call this function with analyzeNewStock(MyStock.class).
As this is a rather complicated and error-prone approach, you’d rather define an interface that creates Stock instances:
public interface StockProvider {
Stock createStock(String value);
}
public class MyStockProvider implements StockProvider {
private final String valueTwo;
public MyStockProvider(String valueTwo) {
this.valueTwo = valueTwo;
}
#Override
public Stock createStock(String valueOne) {
return new MyStock(valueOne, valueTwo);
}
}
public class MyOtherClass {
public void analyzeNewStock(StockProvider provider) {
provider.createStock("Hi!").analyze();
}
public static void main(String[] args) {
analyzeNewStock(new MyStockProvider("Hey!"));
}
}
In Java you can pass a Class. You can do it like this:
private void function(Class c)
This is not very common procatice though. You can probably get wha you need by looking into Strategy pattern, or proper use of Object Oriented Programming (polymorphism).
If you are looking for a way to build some objects, look into Factory pattern.
If you want to create a generic class- look into this detailed answer: https://stackoverflow.com/a/1090488/1611957
You could use generics. For example:
private <T> void function(Class<T> clazz) {
try{
T t = clazz.newInstance();
//more code here
}catch(InstantiationException | IllegalAccessException ex){
ex.printStackTrace();
}
}
The Class<T> clazz shows what type to instantiate. The try/catch is just to prevent errors from stopping your code. The same idea is expanded in this SO post. More info here.
However, I'm not really sure why you would want to do this. There should easily be a workaround using a simple interface. Since you already know that you want an object with type Stock, you could pass an implementation of the interface. For example:
//interface to implement
public interface Stock {
public void analyze();
}
//rewrite of function
private void function(Stock s){
s.analyze();
}
And using two ways to call function:
//first way
public class XYZ implements Stock{
public void analyze(){
//some code here
}
}
//calling the function
function(new XYZ());
//second way
function(new Stock(){
public void analyze(){
//your code here
}
});

How can I dispatch based on a value of a parameter in Java?

There is a recurring pattern when I have for example an enum or a String and I want to dispatch based on the value of that parameter:
public void myMethod(String parameter) {
if(parameter.equals(something)) {
doSomething();
} else if(parameter.equals(somethingElse)) {
doSomethingElse();
}
}
What is the idiomatic way to get rid of the lengthy if or case statements? I'm thinking about something like the single dispatch generic functions in python but I want to dispatch based on value not on type.
#fun.register(int)
def _(arg, verbose=False):
if verbose:
print("Strength in numbers, eh?", end=" ")
print(arg)
#fun.register(list)
def _(arg, verbose=False):
if verbose:
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem)
I find that this is most common when dealing with forms (as an example) that have multiple "actions". Although this may seem overkill, a lot of times it's actually much cleaner (and in many ways, easier) to simply "register" action handlers.
public class Dispatcher {
private Map<String, ActionHandler> actionHandlerMap = new HashMap<String, ActionHandler>();
public void perform(String action) {
ActionHandler handler = actionHandlerMap.get(action);
if (null == handler) {
// no handler - throw an exception?
}
handler.execute();
}
public void addActionHandler(ActionHandler handler) {
actionHandlerMap.put(handler.getAction(), handler);
}
}
public interface ActionHandler {
public String getAction();
public void execute();
}
It is absolutely more code, but it's extensible, clean, and allows for a better separation of concerns. It's also much more easily testable which is always a good thing.
you could use method overriding in java.. so the equivalent should be something like
public void doSomething(String arg) {
//do something when param is string
}
public void doSomething(List<String> arg) {
//do something else when param is a List of String
}
In Java enum is a class as well, so you could extextend it and use it as :
interface Doable {
void doSomething();
}
enum Stuff implements Doable {
ONE() {
public doSomething() { System.out.println("do one");};
},
TWO() {
public doSomething() { System.out.println("do two");};
}
}
Doable s = Stuff.valueOf("ONE");
s.doSomething();

How to overload a method with generic parameter in java? [duplicate]

I have FinanceRequests and CommisionTransactions in my domain.
If I have a list of FinanceRequests each FinanceRequest could contain multiple CommisionTransactions that need to be clawed back. Dont worry how exactly that is done.
The class below (very bottom) makes me feel all fuzzy and warm since its succint and reuses existing code nicely. One problem Type erasure.
public void clawBack(Collection<FinanceRequest> financeRequestList)
public void clawBack(Collection<CommissionTrns> commissionTrnsList)
They both have the same signature after erasure, ie:
Collection<FinanceRequest> --> Collection<Object>
Collection<CommissionTrns> --> Collection<Object>
So eclipse complainst that:
Method clawBack(Collection) has the same erasure clawBack(Collection) as another method in type CommissionFacade
Any suggestions to restructure this so that it still an elegant solution that makes good code reuse?
public class CommissionFacade
{
/********FINANCE REQUESTS****************/
public void clawBack(FinanceRequest financeRequest)
{
Collection<CommissionTrns> commTrnsList = financeRequest.getCommissionTrnsList();
this.clawBack(commTrnsList);
}
public void clawBack(Collection<FinanceRequest> financeRequestList)
{
for(FinanceRequest finReq : financeRequestList)
{
this.clawBack(finReq);
}
}
/********COMMISSION TRANSACTIOS****************/
public void clawBack(CommissionTrns commissionTrns)
{
//Do clawback for single CommissionTrns
}
public void clawBack(Collection<CommissionTrns> commissionTrnsList)
{
for(CommissionTrns commTrn : commissionTrnsList)
{
this.clawBack(commTrn);
}
}
}
Either rename the methods, or use polymorphism: use an interface, and then either put the clawback code in the objects themselves, or use double-dispatch (depending on your design paradigm and taste).
With code in objects that would be:
public interface Clawbackable{
void clawBack()
}
public class CommissionFacade
{
public <T extends Clawbackable> void clawBack(Collection<T> objects)
{
for(T object: objects)
{
object.clawBack();
}
}
}
public class CommissionTrns implements Clawbackable {
public void clawback(){
// do clawback for commissions
}
}
public class FinanceRequest implements Clawbackable {
public void clawBack(){
// do clwaback for FinanceRequest
}
}
I prefer this approach, since I'm of the belief your domain should contain your logic; but I'm not fully aware of your exact wishes, so I'll leave it up to you.
With a double dispatch, you would pass the "ClawbackHandler" to the clawback method, and on the handler call the appropriate method depending on the type.
I think your best option is to simply name the method differently.
public void clawBackFinReqs(Collection<FinanceRequest> financeRequestList) {
}
public void clawBackComTrans(Collection<CommissionTrns> commissionTrnsList) {
}
In fact, it's not too bad, since you don't get anything extra out of having the same name on them.
Keep in mind, that the JVM will not decide which method to call at runtime. As opposed to virtual methods / method overriding resolution of overloaded methods are done at compile time. The Java Tutorials on method overloading even points out that "Overloaded methods should be used sparingly...".
Here is a trick with overloading by the second varargs parameter for the CommissionFacade class from the question:
public class CommissionFacade {
public void clawBack(Collection<FinanceRequest> financeRequestList, FinanceRequestType ...ignore) {
// code
}
public void clawBack(Collection<CommissionTrns> commissionTrnsList, CommissionTrnsType ...ignore) {
// code
}
/*******TYPES TO TRICK TYPE ERASURE*******/
private static class FinanceRequestType {}
private static class CommissionTrnsType {}
}
The code snippet to fast-check this trick works:
import java.util.ArrayList;
class HelloType {
public static void main(String[] args) {
method(new ArrayList<Integer>());
method(new ArrayList<Double>());
}
static void method(ArrayList<Integer> ints, IntegerType ...ignore) {
System.out.println("Hello, Integer!");
}
static void method(ArrayList<Double> dbs, DoubleType ...ignore) {
System.out.println("Hello, Double!");
}
static class IntegerType {}
static class DoubleType {}
}

Categories

Resources