Creating an object based on the subclasses of two other objects - java

My design problem is as follows.
I have two classes, each with a number of subclasses. I have a factory, which needs to create an object based on the subclass of each of these objects.
This is an authentication problem. The factory generates a rule object based on the type of person and the type of resource they wish to access. The rule has alwaysAllow, NeverAllow and timeBasedAllow subclasses. With the potential for more if a more complex access system is needed in the future.
So in future ideally a new person could be created with a new subclass, a new resource with a new subclass. The parameters on which access is determined could be changed with a new rule subclass, and the specific access of each person type and room type could be changed within the rule factory.
So far the only way I can think to do this would be to have an enumeration inside the subclasses, which defeats the point because then adding a new person or room requires a new class and a change in the enum class which seems messy.
I also am very keen to keep the data and the logic separate so I can’t just move authentication methods into the person class because this would require the person class to know how many room types there were, which is definitely not ideal.
I may be after something that isn’t realistically achievable but I can’t help the feeling that there is a nice clean solution just out of my grasp.
Any help would be greatly appreciated.

Your question title makes it sound as if you are searching for multiple-inheiritance, which is not allowed in Java. Unlike in C++, a class may extend one and only one class. However, Java also has interface, which I suspect may be what you seek.
An interface class cannot be instantiated, and may have abstract methods. A
concrete class may implement as many interfaces as desired, and the concrete class must implement each abstract method the interface declares. Abstract classes may also implement interfaces, and abstract methods they do not implement must be implemented by concrete classes extending them.
I suggest extracting your authentication methods into aninterface, perhaps called AuthRule or somesuch. AuthRule can have abstract methods with represent authenticating, without exposing the exact style used to authenticate. So, you would implement AlwaysAllow implements AuthRule and then the authenticate methods on AlwaysAllow would always return true.
The second thing, however, is that you appear to be attempting to use inheritance when composition would better suit your needs. Now instread of having a Person inherit his authentication-rule, the rule should instead be a member field inside Person. So, for example:
class Person extends User {
AuthRule rule;
Person(AuthRule myrule) {
rule = myrule;
}
bool authenticate(...) {
return rule.authenticate(...);
}
}
If you follow a design pattern based on injecting objects into other objects to mix in the functionality you desire, your code will become far more usable and extensible. I hope this helps your problem.

Related

Java inheritance, two-step inheritance

I have the main abstract class that is a base for bunch of classes. Some of them does not need all the fields and methods from the main abstract class, so I have created second abstract class and splitted main abstract class into two parts. The main abstract class contains, for example, a, x fields and their getters/setters, the second abstract class inherits from the main and contains additional b, c fields and their getter/setters. There are simple classes that are inheriting from the main class,and more complicated are inheriting from the second class. I want to create objects of each class as instances of the main class. Is it right way to do that? I have to type check and cast when I want to use methods from the second abstract class. It makes my code complicated. How can I solve this problem?
MainAbstractClass ---> SecondAbstractClass ---> MyComplicatedClasses
|
|
V
MySimpleClasses
One of the OO principles is Favor composition over inheritance.
This means that common behavior is not provided through base classes but via Component classes which are passed in via dependency injection (preferably as constructor parameters.
The answer depends on your actual needs.
You can instead choose to store the extended abstract class specific fields in a class that does not implement your base class and make it a member of more complicated classes.
You can choose to keep everything in a single base class and nothing forces you to use all the fields of an interface in every class that implemented your interface.
You can also keep using your approach but since you store the classes as an instance of the base class, it will be hard to read.
I believe that if you think code does not look very good, it is probably not good. However, there is usually no single answer to this kind of design questions and the best solution is relative to your preferences.
I think this need of type cast is a smell of fragile design. Here when we assume MyComplicatedClass ISA KIND OF MainAbstractClass as shown by TJ Crowder then object must behave as MainAbstractClass (meaning it can honor only API of MainAbstractClass). If it expects special treatment as MyComplicatedClass its false commitment and will need Casting. Such casting (by identifying type) goes against OO principles and kills polymorphism. Later this will end up in Ladder of InstanceOf and type casts as in the scenarios rightly pointed out by T.J. Crowder.
I would suggest readdress the design. e.g. though our all user defined type instances ARE KIND OF Object, but we use Object API only for methods defined in Object class. We do not use Object o = new MyClass(). There are occasions in frameworks or like Object.equals() method where type cast is needed as API is defined before even concrete extension is written. But it is not a good idea for such simple complete (without open hooks for extensions) Hierarchies.

A design confusion about inheritance and interfaces

I'm stuck with a rather peculiar design problem. I'm using a Java ORM, and have defined one of my model classes as follows:
class User extends Model {
// . . .
}
Now, there are more models, and I'd like them all to support data validations. The idea is simple: As each setter method is called, an internal ArrayList of errors keeps getting populated.
Now, the mechanism of error handling is exactly the same for all the model classes. I can envision the following interface:
public interface ErrorReportable {
ArrayList<String> errors = new ArrayList<String>();
boolean hasErrors();
ArrayList<String> getErrors();
void resetErrors();
}
Now I have a problem: All the methods are abstract, which means I'll have to provide an implementation for all of them in my classes. This is sad, because all these methods are going to be implemented in exactly the same way. Ideally, this would've been another class I would've neatly inherited from, but sadly, there's no multiple inheritance in Java.
My next option is use default methods in interfaces, but here the problem is the errors field, which will become static whereas I need a regular field for each instance.
It looks like the only solution is composition, but then I'll have to have a hasErrors() method on User, which will go return this.error_obj.hasErrors(). This is fine, but not really neat in my opinion as I'm having to write things twice.
How can I do better?
I think it would be better for the model classes to only expose List<Error> validate() method, and to have a stand-alone validator that validates all the fields and collects the errors.
That way, the collected messages are not part of the model's state, you have explicit control over when will the validation happen, you're preferring composition (which is almost always a good thing), and the only method you need to implement in model class is the entity-specific validation.
If you ever need to add any cross-field validations, it will also be probably quite easy to extend this design to also perform those alongside with field validations.
If I get your need right, I would implement an own Model-class, that implements all neceaasary Interfaces and extends the Model-ancestor, but still is Abstract.
Then all your normal model-classes inherit from your abstract model-class to get the implementation for the interface and also the inheritance from the model-class (2nd Generation would that be). Any framework checking with 'instance of' will still check true for the later model-class.
The abstract class does not even have to have any abstract methods/members, but it should stay abstract to prevent direct instanciating from that class.
public abstract class myModel extends Model implements ErrorReportable{ ... }
public class User extends myModel { ... }

How to get around the lack of abstract fields in Java?

Assume, we have an abstract class A and we want to force all subclasses to have a certain field. This is not possible in Java, because we can not define abstract fields.
Workaround 1: Force subclasses to implement a method which delivers the wanted value.
abstract class A {
abstract int getA();
}
Drawback: Each subclass has to implement a method for each abstract field we want to have. This can lead to many method implementations.
Advantage: We can use the method getA in the abstract class and implement methods with it in A without implementing them in each subclass. But the value behind the method can not be overwritten by the abstract class.
Workaround 2: Simulate the abstract field by forcing the subclass to give the abstract class a value.
abstract class A {
int a;
public A(int a) {
this.a = a;
}
}
Drawback: When we have multiple fields (> 10), the super constructor call will look a bit ugly and confusing.
Advantage: We can use the field a in the abstract class and implement methods with it in A without implementing them in each subclass. Plus, the value a can be overwritten by the abstract class.
Question: Which workaround is the common way to reach the goal ? Maybe there is a better one than the above ones ?
The abstract method is probably the most object oriented.
If you have too many fields, you may want to regroup those in a POJO (if a new concept is appropriate).
I prefer the first one . i dont love to couple classes in fileds name , how they handle state and how they save it. the first one is more close to open/close principal
I recommend to avoid inheritance. inheritance is very frigle and hard to maintenance. remember effective java advice - prefer composition other inheritance
I think opt.1 is the cleaner by far. A few getters and setters is not a big deal, and I doubt that many use cases would have more than just a few abstract "fields".
About opt.2, you forget that constructors are not inherited, and thus would require all sub classes constructors to be implemented in a way that takes a into account.
Workaround 2 is very common because of 2 advantages:
1) the one you mentioned - the field does not belong to the subclass - it belongs to the parent and that is important because it was "demanded" by the parent and because the parent can use it
2) When sub-classing from the parent you are very aware of this field because when you implement the constructor you must pass it on. If I saw the first workaround I wouldn't know what to understand from it, in this way I understand that the parent class needs this field to work, so it must have a meaningful value.
note: if you have a class that has 10 fields that need to be initialized something is probably wrong in your design.
1. Actually its not about what one prefers but its about the flexibility, and the ability
to adapt changes.
2. Its always better to Encapsulate Behaviors that keeps changing, either into an Interface or Abstract class.
3. You 1st Workaround will be good in places where you need different implementation for the same Behavior in Different classes. Then at this place either an Interface or your 1st Workaround will be a good choice.
Eg:
Consider Painting as a Class with paint() Method.
Now
paint() method can have Stroking, gliding, shading etc styles of doing it.
Then its better to Encapsulate that method into an Abstract class or an Interface.
public interface Paint{
paintDoIt(String style);
}
4. Your 2nd Wordaround will be good in a place, where you want certain behaviors to be MUST implemented by the Subclass.
Eg:
Consider Car as an Abstract Class, Now to be car its very important that it must have
a Steering, 4 wheels, Engine, etc. So these features must be implemented.
where as other features like music system, LCD ,etc are optional and depends on the car type.

Abstract class vs Interface in Java

I was asked a question, I wanted to get my answer reviewed here.
Q: In which scenario it is more appropriate to extend an abstract class rather than implementing the interface(s)?
A: If we are using template method design pattern.
Am I correct ?
I am sorry if I was not able to state the question clearly.
I know the basic difference between abstract class and interface.
1) use abstract class when the requirement is such that we need to implement the same functionality in every subclass for a specific operation (implement the method) and different functionality for some other operations (only method signatures)
2) use interface if you need to put the signature to be same (and implementation different) so that you can comply with interface implementation
3) we can extend max of one abstract class, but can implement more than one interface
Reiterating the question: Are there any other scenarios, besides those mentioned above, where specifically we require to use abstract class (one is see is template method design pattern is conceptually based on this only)?
Interface vs. Abstract class
Choosing between these two really depends on what you want to do, but luckily for us, Erich Gamma can help us a bit.
As always there is a trade-off, an interface gives you freedom with regard to the base class, an abstract class gives you the freedom to add new methods later. – Erich Gamma
You can’t go and change an Interface without having to change a lot of other things in your code, so the only way to avoid this would be to create a whole new Interface, which might not always be a good thing.
Abstract classes should primarily be used for objects that are closely related. Interfaces are better at providing common functionality for unrelated classes.
When To Use Interfaces
An interface allows somebody to start from scratch to implement your interface or implement your interface in some other code whose original or primary purpose was quite different from your interface. To them, your interface is only incidental, something that have to add on to the their code to be able to use your package. The disadvantage is every method in the interface must be public. You might not want to expose everything.
When To Use Abstract classes
An abstract class, in contrast, provides more structure. It usually defines some default implementations and provides some tools useful for a full implementation. The catch is, code using it must use your class as the base. That may be highly inconvenient if the other programmers wanting to use your package have already developed their own class hierarchy independently. In Java, a class can inherit from only one base class.
When to Use Both
You can offer the best of both worlds, an interface and an abstract class. Implementors can ignore your abstract class if they choose. The only drawback of doing that is calling methods via their interface name is slightly slower than calling them via their abstract class name.
reiterating the question: there is any other scenario besides these
mentioned above where specifically we require to use abstract class
(one is see is template method design pattern is conceptually based on
this only)
Yes, if you use JAXB. It does not like interfaces. You should either use abstract classes or work around this limitation with generics.
From a personal blog post:
Interface:
A class can implement multiple interfaces
An interface cannot provide any code at all
An interface can only define public static final constants
An interface cannot define instance variables
Adding a new method has ripple effects on implementing classes (design maintenance)
JAXB cannot deal with interfaces
An interface cannot extends or implement an abstract class
All interface methods are public
In general, interfaces should be used to define contracts (what is to be achieved, not how to achieve it).
Abstract Class:
A class can extend at most one abstract class
An abstract class can contain code
An abstract class can define both static and instance constants (final)
An abstract class can define instance variables
Modification of existing abstract class code has ripple effects on extending classes (implementation maintenance)
Adding a new method to an abstract class has no ripple effect on extending classes
An abstract class can implement an interface
Abstract classes can implement private and protected methods
Abstract classes should be used for (partial) implementation. They can be a mean to restrain the way API contracts should be implemented.
Interface is used when you have scenario that all classes has same structure but totally have different functionality.
Abstract class is used when you have scenario that all classes has same structure but some same and some different functionality.
Take a look the article : http://shoaibmk.blogspot.com/2011/09/abstract-class-is-class-which-cannot-be.html
There are a lot of great answers here, but I often find using BOTH interfaces and abstract classes is the best route. Consider this contrived example:
You're a software developer at an investment bank, and need to build a system that places orders into a market. Your interface captures the most general idea of what a trading system does,
1) Trading system places orders
2) Trading system receives acknowledgements
and can be captured in an interface, ITradeSystem
public interface ITradeSystem{
public void placeOrder(IOrder order);
public void ackOrder(IOrder order);
}
Now engineers working at the sales desk and along other business lines can start to interface with your system to add order placement functionality to their existing apps. And you haven't even started building yet! This is the power of interfaces.
So you go ahead and build the system for stock traders; they've heard that your system has a feature to find cheap stocks and are very eager to try it out! You capture this behavior in a method called findGoodDeals(), but also realize there's a lot of messy stuff that's involved in connecting to the markets. For example, you have to open a SocketChannel,
public class StockTradeSystem implements ITradeSystem{
#Override
public void placeOrder(IOrder order);
getMarket().place(order);
#Override
public void ackOrder(IOrder order);
System.out.println("Order received" + order);
private void connectToMarket();
SocketChannel sock = Socket.open();
sock.bind(marketAddress);
<LOTS MORE MESSY CODE>
}
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
The concrete implementations are going to have lots of these messy methods like connectToMarket(), but findGoodDeals() is all the traders actually care about.
Now here's where abstract classes come into play. Your boss informs you that currency traders also want to use your system. And looking at currency markets, you see the plumbing is nearly identical to stock markets. In fact, connectToMarket() can be reused verbatim to connect to foreign exchange markets. However, findGoodDeals() is a much different concept in the currency arena. So before you pass off the codebase to the foreign exchange wiz kid across the ocean, you first refactor into an abstract class, leaving findGoodDeals() unimplmented
public abstract class ABCTradeSystem implements ITradeSystem{
public abstract void findGoodDeals();
#Override
public void placeOrder(IOrder order);
getMarket().place(order);
#Override
public void ackOrder(IOrder order);
System.out.println("Order received" + order);
private void connectToMarket();
SocketChannel sock = Socket.open();
sock.bind(marketAddress);
<LOTS MORE MESSY CODE>
}
Your stock trading system implements findGoodDeals() as you've already defined,
public class StockTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
but now the FX whiz kid can build her system by simply providing an implementation of findGoodDeals() for currencies; she doesn't have to reimplement socket connections or even the interface methods!
public class CurrencyTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
ccys = <Genius stuff to find undervalued currencies>
System.out.println("The best FX spot rates are: " + ccys);
}
Programming to an interface is powerful, but similar applications often re-implement methods in nearly identical ways. Using an abstract class avoids reimplmentations, while preserving the power of the interface.
Note: one may wonder why findGreatDeals() isn't part of the interface. Remember, the interface defines the most general components of a trading system. Another engineer may develop a COMPLETELY DIFFERENT trading system, where they don't care about finding good deals. The interface guarantees that the sales desk can interface to their system as well, so it's preferable not to entangle your interface with application concepts like "great deals".
Which should you use, abstract classes or interfaces?
Consider using abstract classes if any of these statements apply to your use case:
You want to share code among several closely related classes.
You expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (such as protected and private).
You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong.
Consider using interfaces if any of these statements apply to your use case:
You expect that unrelated classes would implement your interface.
For example, the interfaces Comparable and Cloneable are implemented by many unrelated classes.
You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.
You want to take advantage of multiple inheritance of type.
New methods added regularly to interface by providers, to avoid issues extend Abstract class instead of interface.
http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Things have been changed a lot in last three years with addition of new capabilities to interface with Java 8 release.
From oracle documentation page on interface:
An interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods.
As you quoted in your question, abstract class is best fit for template method pattern where you have to create skeleton. Interface cant be used here.
One more consideration to prefer abstract class over interface:
You don't have implementation in base class and only sub-classes have to define their own implementation. You need abstract class instead of interface since you want to share state with sub-classes.
Abstract class establishes "is a" relation between related classes and interface provides "has a" capability between unrelated classes.
Regarding second part of your question, which is valid for most of the programming languages including java prior to java-8 release
As always there is a trade-off, an interface gives you freedom with regard to the base class, an abstract class gives you the freedom to add new methods later. – Erich Gamma
You can’t go and change an Interface without having to change a lot of other things in your code
If you prefer abstract class to interface earlier with above two considerations, you have to re-think now as default methods have added powerful capabilities to interfaces.
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
To select one of them between interface and abstract class, oracle documentation page quote that:
Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.
With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.
Refer to these related questions fore more details:
Interface vs Abstract Class (general OO)
How should I have explained the difference between an Interface and an Abstract class?
In summary : The balance is tilting more towards interfaces now.
Are there any other scenarios, besides those mentioned above, where specifically we require to use abstract class (one is see is template method design pattern is conceptually based on this only)?
Some design patterns use abstract classes (over interfaces) apart from Template method pattern.
Creational patterns:
Abstract_factory_pattern
Structural patterns:
Decorator_pattern
Behavioral patterns:
Mediator_pattern
You are not correct. There are many scenarios. It just isn't possible to reduce it to a single 8-word rule.
The shortest answer is, extend abstract class when some of the functionalities uou seek are already implemented in it.
If you implement the interface you have to implement all the method. But for abstract class number of methods you need to implement might be fewer.
In template design pattern there must be a behavior defined. This behavior depends on other methods which are abstract. By making sub class and defining those methods you actually define the main behavior. The underlying behavior can not be in a interface as interface does not define anything, it just declares. So a template design pattern always comes with an abstract class. If you want to keep the flow of the behavior intact you must extend the abstract class but don't override the main behavior.
In my opinion, the basic difference is that an interface can't contain non-abstract methods while an abstract class can.
So if subclasses share a common behavior, this behavior can be implemented in the superclass and thus inherited in the subclasses
Also, I quoted the following from "software architecture design patterns in java" book
" In the Java programming language, there is no support for multiple inheritance.
That means a class can inherit only from one single class. Hence inheritance
should be used only when it is absolutely necessary. Whenever possible, methods
denoting the common behavior should be declared in the form of a Java interface to be implemented by different implementer classes. But interfaces suffer from the limitation that they cannot provide method implementations. This means that every implementer of an interface must explicitly implement all methods declared in an interface, even when some of these methods represent the invariable part of the functionality and have exactly the same implementation in all of the implementer classes. This leads to redundant code. The following example demonstrates how the Abstract Parent Class pattern can be used in such cases without requiring redundant method implementations."
Abstract classes are different from interfaces in two important aspects
they provide default implementation for chosen methods (that is covered by your answer)
abstract classes can have state (instance variables) - so this is one more situation you want to use them in place of interfaces
This is a good question The two of these are not similar but can be use for some of the same reason, like a rewrite. When creating it is best to use Interface. When it comes down to class, it is good for debugging.
This is my understanding, hope this helps
Abstract classes:
Can have member variables that are inherited (can’t be done in interfaces)
Can have constructors (interfaces can’t)
Its methods can have any visibility (ie: private, protected, etc - whereas all interface methods are public)
Can have defined methods (methods with an implementation)
Interfaces:
Can have variables, but they are all public static final variables
constant values that never change with a static scope
non static variables require an instance, and you can’t instantiate an interface
All methods are abstract (no code in abstract methods)
all code has to be actually written in the class that implements the particular interface
Usage of abstract and interface:
One has "Is-A-Relationship" and another one has "Has-A-Relationship"
The default properties has set in abstract and extra properties can be expressed through interface.
Example: --> In the human beings we have some default properties that are eating, sleeping etc. but if anyone has any other curricular activities like swimming, playing etc those could be expressed by Interface.
Abstract classes should be extended when you want to some common behavior to get extended. The Abstract super class will have the common behavior and will define abstract method/specific behavior which sub classes should implement.
Interfaces allows you to change the implementation anytime allowing the interface to be intact.
I think the answers here are missing the main point:
Java interfaces (the question is about Java but there are similar mechanisms in other languages) is a way to partially support multiple inheritance, i.e. method-only inheritance.
It is similar to PHP's traits or Python's duck typing.
Besides that, there is nothing additional that you truly need an interface for --and you cannot instantiate a Java interface.

Why is having an abstract subclass of concrete class bad design?

After all ANY java abstract is an abstract subclass of Object. Sometimes we need to force the subclass to implement some methods, but may already have a pretty well defined hierarchy with concrete classes.
For example: I have a well functioning hierarchy with
Vehicle<--- Car
and now I want to add ElectricCar to this hierarchy.
vehicle<--Car<--ElectricCar.
I also want all the different types of electric cars to implement certain behaviors like getBatteryLife or something-
Why would it be a bad idea to make ElectricCar abstract ?
there's nothing wrong in making it abstract. if your business requires you to make it abstract, it's fine. Like you said, lots of classes in Java lib are abstract and still extending Object.
It's not bad, per se. Not common, but not bad. The only thing I can think of is understandability: if I saw a concrete class Car that I could instantiate, I would normally assume that any child of it was also instantiable, because 99% of code works this way.Then I'd be confused, for a second, about not being able to instantiate an ElectricCar.
It could be argued that this pattern breaks the Liskov Substituion Principle since you can't pass "ElectricCar" wherever "Car" is expected if it's declared abstract (you could pass instances of ElectricCar subclasses of course).
In this particular example, the concrete electric cars (hydrogen powered/plug-in/etc?) I would expect to inherit directly from "Car" since they satisfy an "is-a" relationship and are a proper specialisation of "Car". If you wanted to described some common behaviours and traits they should provide then they should also implement an ElectricCar interface.
It seems what you really want is the ability to inherit from Car (since that is what they are) and share/re-use common implementations of electric car related methods. In this case you are looking at a multiple inheritance problem or a need for mixins, neither of which are directly supported in Java.
Providing an abstract class in the middle of a concrete hierarchy may be one way around this, but it's not pretty.
Personally I would prefer to define an Interface for ElectricCar and then allow the implementing class to define the methods. Then you can share the behavior of getBatteryLife through another mechanism.
I've built some pretty deep hierarchies of Inheritance and I tend to avoid them do to the brittle nature they tend to build up over time. One Base class might make sense, but I would think about how you can compose your object model to share behavior w/o inheritance if possible.
In you example I would say that supposedly the Car class should be abstract (or an interface), too. But there is nothing wrong with the ElectricCar being abstract.

Categories

Resources