Class design question [optional implementation] - java

I was wondering how to design a system in which I have a class Super and a couple of classes that are subclasses of Super (let's say Sub1, Sub2, Sub3) and I want a class Cool. Now there are two things I want to have:
Sub1 and Sub2 can be Cool's, Sub3 can never be cool.
I must be able to have a List in which there can be Sub1's and Sub2's, if they are cool. If for example I make an object of Sub1 and it is cool I can put it in the list, if it's not it cannot be in the list.
Any suggestions? Hints?

Arne's answer kind of does what you want, but I find it overly complicated. Maybe I'm missing something? Why not just:
class Super { }
interface Cool { boolean isCool(); }
class CoolImpl extends Super implements Cool {
private boolean cool;
public CoolImpl(boolean cool) { this.cool = cool; }
public boolean isCool() { return this.cool; }
}
class Sub1 extends CoolImpl { }
class Sub2 extends CoolImpl { }
class Sub3 extends Super { }
class CoolList extends ArrayList<Cool> {
public boolean add(Cool cool) {
if (!cool.isCool()) {
return false;
}
return super.add(cool);
}
}

Maybe something like this:
class Super {}
interface Cool { boolean isCool(); }
class IsCool implements Cool {
public boolean isCool() { return true; }
}
class NotCool impolements Cool {
public boolean isCool() { return false; }
}
interface CoolSupporter {
boolean isCool();
Cool getCool();
}
class Sub1 extends Super implements CoolSupporter {
private Cool cool;
public Sub1() { this(new NotCool()); }
public Sub1(Cool cool) { this.cool = cool; }
public boolean isCool() { this.cool.isCool(); }
public Cool getCool() { return this.cool; }
}
class Sub2 extends Super implements CoolSupporter {
private Cool cool;
public Sub1() { this(new NotCool()); }
public Sub1(Cool cool) { this.cool = cool; }
public boolean isCool() { this.cool.isCool(); }
public Cool getCool() { return this.cool; }
}
class Sub3 extends Super {}
class CoolList {
private List<CoolSupporter> list = new ArrayList<CoolSupporter>();
public void add(CoolSupporter coolSupporter) {
if (coolSupporter.isCool()) {
list.add(coolSupporter);
} else {
throw new UncoolException();
}
}
}

You can create an marker interface say cool.
Let class Sub1 and Sub2 implements this interface
and before adding to the list check for instance of cool
may be this can help.

You can't have a class optionally belonging to a type in Java. Though you may subclass Sub1, with one subclass implementing an interface Cool and the other not:
class Super { }
interface Cool { }
class Sub1 extends Super { }
class Sub1Cool extends Sub1 implements Cool { }
class Sub2 extends Super { }
class Sub2Cool extends Sub2 implements Cool { }
class Sub3 extends Super { }
class CoolList extends ArrayList<Super> {
public boolean add(Super sup) {
if (!(sup instanceof Cool)) {
return false;
}
return super.add(cool);
}
}
You might also discard the Cool concept and use a visitor pattern:
class Super {
public boolean addTo(List<Super> coolList) {
if (canBeAddedToCoolList()) {
return coolList.add(this);
}
return false;
}
protected boolean canBeAddedToCoolList() {
return false;
}
}
class Sub1 extends Super {
protected boolean canBeAddedToCoolList() {
// check logic to allow/disallow addition
}
}

IMO, you need to have a overrided List (Say MyList, that overrides add()).
In add(), Check if the object you are adding is Cool, if it is so, then add it part of the list. If not then just gracefully disregard it.
Does this help?

The simplest way you can manage this is to further subclass Sub1 (CoolSub1 and NotCoolSub1) and Sub2 (CoolSub2 and NotCoolSub2).
CoolSub1 and CoolSub2 can then implement Cool ( Cool should be an interface and not a class)
You can then define
List<Cool>
which will accept implementations of Sub1 and Sub2, but only if they implement Cool.

Related

I don't understand why my generic type declaration doesn't match

Here are the classes declarations:
public interface IPoint<N extends Number> {
...
}
public abstract class PointP<N extends Number> implements IPoint<N> {
...
}
public class Pointf extends PointP<Float> {
...
}
public interface ISegment<T extends Number, P extends IPoint<T>> {
...
}
public abstract class SegmentP<N extends Number, P extends IPoint<N>> implements ISegment<N, P> {
...
}
public class Segmentf extends SegmentP<Float, Pointf> {
...
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, IPoint<N>>> implements Iterable<S>, Iterator<S> {
...
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
...
}
The compiler refuses the Segmentf type in the generic declaration of the LinesfIterator class with the error message:
Bound mismatch: The type Segmentf is not a valid substitute for the bounded parameter <S extends ISegment<N,IPoint<N>>> of the type LinesPIterator<N,S>
However for me everything seems correct. The declaration of the LinesfIterator class seems to me to have the same hierarchical schema as the Segmentf class which compiles without problem.
Is there a solution to this way of doing things?
As already said, your hierarchy seems to be unnecessarily complex and shall be simplified. For example, I see no meaning in Pointf -> PointP -> IPoint the hierarchy.
If you want to fix your issue, you have to allow a subtype ? extends IPoint<N> in the LinesPIterator class, so:
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>>
implements Iterable<S>, Iterator<S>
{
// ...
}
Moreover, there would be better to implement only Iterable as long as it provides an Iterator and you might end up with duplicated implementation.
public static class LinesfIterator extends LinesPIterator<Segmentf, Pointf, Float> {
#Override
public Iterator<Segmentf> iterator() {
return new Iterator<Segmentf>() {
#Override
public boolean hasNext() { /* TO DO */ }
#Override
public Segmentf next() { /* TO DO */ }
};
}
}
This remark on the use of an anonymous class rather than a direct use really caught my attention because intuitively, when I can avoid going through an anonymous class I do. On the one hand because it is an additional instantiation and on the other hand because it is more difficult to identify at debug (when they are several in the same class).
And I can't see the reasons why I should prefer the use of an anonymous class for this case.
Maybe with my classes as an example the explanation will be easier.
for(Segmentf segment : new LinesfIterator(cube.getPoints(), cube.getIndices())) {
System.out.println(segment);
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>> implements Iterable<S>, Iterator<S> {
private N[][] points;
private int[] indices;
private int count;
public LinesPIterator(N[][] points, int[] indices) {
super();
this.points = points;
this.indices = indices;
}
protected abstract S instanciateIteration(final N[] pointDeb, final N[] pointFin);
#Override
public Iterator<S> iterator() {
return this;
}
#Override
public boolean hasNext() {
return count < (indices.length - 1);
}
#Override
public S next() {
return instanciateIteration(points[indices[count++]], points[indices[count++]]);
}
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
public LinesfIterator(Float[][] points, int[] indices) {
super(points, indices);
}
#Override
protected Segmentf instanciateIteration(Float[] point1, Float[] point2) {
return new Segmentf(point1, point2);
}
}

Abstract method with different parameters Java

public abstract class CommonClass {
abstract void send(<what should i put here???>) {}
}
public class ClassA extends CommonClass {
void send(List<Comments> commentsList) {
// do stuff
}
}
public class ClassB extends CommonClass {
void send(List<Post> postList) {
// do stuff
}
}
I am new to OODP, I am trying to have a method that is able to take in any kind of List data so that I can abstract things out. How can i do this?
You could make it generic on some type T. Like,
public abstract class CommonClass<T> {
abstract void send(List<T> al);
}
And then, to implement it - use the generic. Like,
public class ClassA extends CommonClass<Comments> {
#Override
void send(List<Comments> commentsList) {
// do stuff
}
}
public class ClassB extends CommonClass<Post> {
#Override
void send(List<Post> postList) {
// do stuff
}
}
Also, as discussed in the comments, your class names could be improved to be more intuitive; something like,
public abstract class AbstractSender<T> {
abstract void send(List<T> al);
}
and then
public class CommentSender extends AbstractSender<Comment> {
#Override
void send(List<Comment> commentsList) {
// do stuff
}
}
public class PostSender extends AbstractSender<Post> {
#Override
void send(List<Post> postList) {
// do stuff
}
}
That has the advantage(s) of being more readable and easier to reason about (I can tell what a PostSender does by reading the name, ClassB not so much).
Finally, this looks like a case where an interface would work since your abstract class is purely virtual (and should be preferred since you can implement multiple interface, but can only extend from a single parent class);
public interface ISender<T> {
void send(List<T> al);
}
public class CommentSender implements ISender<Comment> {
#Override
void send(List<Comment> commentsList) {
// do stuff
}
}
public class PostSender implements ISender<Post> {
#Override
void send(List<Post> postList) {
// do stuff
}
}
In order to achieve this, you can take multiple approaches, I would suggest looking into Generics: https://docs.oracle.com/javase/tutorial/java/generics/index.html
With that said, there is one approach that is the most elegant and simple: you can supply a List<T> where T is a generic type.
public abstract class CommonClass<T> {
abstract void send(List<T>) {}
}
public class ClassA extends CommonClass<Comment> {
void send(List<Comments> commentsList) {
// do stuff
}
}
public class ClassB extends CommonClass<Post> {
void send(List<Post> postList) {
// do stuff
}
}
You can do that with the help of generics. https://www.tutorialspoint.com/java/java_generics.htm
Example
The abstract class
public abstract class CommonClass {
public abstract <T> void send(List<T> data);
}
Its child
public class Child extends CommonClass {
public <T> void send(List<T> data) {
// code here
}
}
Retrieving the list's contents
Retrieving the generified list's contents is similar to retrieving any list's contents. In the scope of the method, "T" is a type of object contained in the list.
for (T t : data) {
// to check if t is a string
if (t instanceof String) {
// code
}
}
You can also use lambdas to retrieve every element in the list.

Java Generic Interfaces with multiple implementations

I have the following scenario:
public abstract class BaseTask{...}
public class TaskA extends BaseTask {....}
public class TaskB extends BaseTask {....}
public interface TaskService<T extends BaseTask>{
void process(T task);
}
#Service #Qualifier("taskServiceA")
public class TaskServiceA<TaskA> implements TaskService<TaskA>{
}
#Service #Qualifier("taskServiceB")
public class TaskServiceB<TaskB> implements TaskService<TaskB>{
}
public class ProcessingService{
#Autowired #Qualifier("taskServiceA")
private TaskService<TaskA> taskAService;
#Autowired #Qualifier("taskServiceB")
private TaskService<TaskB> taskBService;
public void process(Order o){
BaseTask task = o.getTask();
getTaskService(o).start(task);
}
private <T extends BaseTask> TaskService<T> getTaskService(Order o){
if("atype".equals(o.type)){
return (TaskService<T>) taskAService;
} else if("btype".equals(o.type)){
return (TaskService<T>) taskBService;
}
}
}
Update: I have reworded the question because the answers I was getting was not what I was looking for.
My questions is related to the getTaskService method.
Why do I need to cast the return value like this
return (TaskService) taskAService;
Is there another way to implement the getTaskService() method without having to do the cast?
I will really appreciate if someone can provide some explanation or better implementation for the getTaskService method.
How about this?
No need of any if conditions.
Later if someone does add another implementation of BaseTask they don't have to change any other code.
Also I recommend changing "atype" to Enum and using Map<EnumTask, ? extends BaseTask> serviceMap; instead of String.
Your final invocation of Tasks can be without any checks
#Service
class ProcessingService {
#Autowired
private TaskServiceManager taskServiceManager;
public void process(Order o){
taskServiceManager.getServiceTask(o.type).start(task);
}
}
Other classes
enum ServiceEnum {
TaskA,
TaskB
}
public class TaskA extends BaseTask {....}
public class TaskB extends BaseTask {....}
public abstract class TaskService<T extends BaseTask>{
public TaskService(ServiceEnum serviceEnum, TaskServiceManager taskServiceManager) {
taskServiceManager.registerTask(serviceEnum, this);
}
void process(T task);
}
#Service #Qualifier("taskServiceA")
public class TaskServiceA<TaskA> implements TaskService<TaskA>{
#Autowired
public TaskA(TaskServiceManager taskServiceManager) {
super(ServiceEnum.TaskA, taskServiceManager);
}
}
#Service #Qualifier("taskServiceB")
public class TaskServiceB<TaskB> implements TaskService<TaskB>{...}
#Service
class TaskServiceManager {
Map<ServiceEnum, ? extends TaskService> serviceMap;
public <T extends TaskService> void registerTask(ServiceEnum serviceName, T task) {
if(serviceMap.containsKey(serviceName)) {
throw new IllegalArgumentException("ServiceName is already in the Map");
}
serviceMap.put(serviceName, task);
}
public <T extends TaskService> T getServiceTask(ServiceEnum serviceName) {
if(!serviceMap.containsKey(serviceName)) {
throw new IllegalArgumentException("ServiceName is not Registered");
}
return serviceMap.get(serviceName);
}
}
Because type T is resolved wherever the method is used. The following statement is valid:
TaskService<TaskA> s = getTaskService(o);
So is:
TaskService<TaskB> s = getTaskService(o);
So within the method getTaskService, you don't know much about T.
The correct way to do this would be:
private TaskService<? extends BaseTask> getTaskService(Order o) {
if ("atype".equals(o.type)) {
return taskAService;
} else if ("btype".equals(o.type)) {
return taskBService;
} else {
return null;
}
}
The assignment above would have to become:
TaskService<? extends BaseTask> s = getTaskService(o);

Java return ArrayList<MyObject> in medhot which returns an ArrayList of an Interface

I have two classes which have to getMethodes which returns an ArrayList of two Objects which implements a interface
public class MyClass1 implements IMyClasses<MyObject1>{
public ArrayList<MyObject1> getMyObject() { ... }
}
public class MyClass2 implements IMyClasses<MyObject1>{
public ArrayList<MyObject1> getMyObject() { ... }
}
MyObject1 and MyObject2 implements IMyObject
In my ManagerClass I would like to implement a function which can return any IMyObject implementation
ArrayList<IMyObject) get() {
if (...) {
return new MyClass1().getMyObject();
} else {
return new MyClass2().getMyObject();
}
}
Before I have introduced the Generic typ on MyClass1 and MyClass2 it worked fine, but with the Generic which I need to get the proper object if needed, I'm not able to return the object which has as return type the Interface?
Some help?
Edit this is a full working example, the trick is to do <? extend IMyObject> thx to #Alexander.Furer
public class ManagerClassTest {
public interface IManagerClass {
public ArrayList<? extends IMyObject> getMyObject(boolean myObject1);
}
public interface IMyClass<I>{
public ArrayList<I> getMyObject();
}
public interface IMyObject {}
public class MyObject1 implements IMyObject {}
public class MyClass1 implements IMyClass<MyObject1> {
#Override
public ArrayList<MyObject1> getMyObject() {
return new ArrayList<MyObject1>();
}
}
public class MyObject2 implements IMyObject {}
public class MyClass2 implements IMyClass<MyObject2> {
#Override
public ArrayList<MyObject2> getMyObject() {
return new ArrayList<MyObject2>();
}
}
public class ManagerClass implements IManagerClass {
private ArrayList<MyObject1> getMyObject1() {
return new MyClass1().getMyObject();
}
private ArrayList<MyObject2> getMyObject2() {
return new MyClass2().getMyObject();
}
#Override
public ArrayList<? extends IMyObject> getMyObject(boolean myObject1) {
if (myObject1) {
return new MyClass1().getMyObject();
} else {
return new MyClass2().getMyObject();
}
}
}
}
ArrayList<MyObject1> is not of type ArrayList<IMyObject> ,BTW, you have a typo :ArrayList<IMyObject)
Declare the get method of ManagerClass as :
ArrayList<? extends IMyObject> get() {
}

using object functions in java

I'm trying to implement function objects in Java. I have a Unit class, with a default addition function that should be used in most initializations of a Unit object. However, for some issues, I need a different addition function. The code will look something like this:
public class Unit() {
public Unit(unitType) {
if (unitType == "specialType") {
additionFunc = defaultFunc } else {
additionFunc = specialFunc }
}
}
public int swim() {
return additionFunc()
}
// definiion of regularFunc
// definition of specialFunc
}
Then, from the main file:
Unit fish = new Unit(regularTyoe);
Unit fatFish = new Unit(specialType);
fish.swim(); //regular function is called
fatFish.swim(); //special function is called
That's it.. does anyone know how this can be done?
You need to look up inheritance and method overriding. It would probably help to read up on proper Object Oriented Programming as well.
The proper way to do this is:
class Fish {
public void swim() {
// normal swim
}
}
class FatFish extends Fish {
#Override
public void swim() {
// special swim
}
}
Fish fish = new Fish()
Fish fatFish = new FatFish()
fish.swim() // normal swim
fatFish.swim() // slow swim
Make a new FatFish class which extends Unit and overrides swim().
Unit fish = new Unit();
Unit fatFish = new FatFish();
fish.swim(); //regular function is called
fatFish.swim(); //special function is called
There are many solutions for your problem, one of them is using inheritance, that you could have a default implementation of Unit, and extend it overriding the desired method with a new one.
Basically would be something like:
public class FatFish {
#Override
public void swim() {
// new behavior
}
}
Another approach would be to implement Strategy Design Pattern, which allows you to select algorithms on runtime. Therefore you could do something like:
public interface SwimStrategy {
void execute();
}
public class FatFishSwimStrategy implements SwimStrategy {
#Override
public void execute() {
// fat fish swim impl
}
}
public class FishSwimStrategy implements SwimStrategy {
#Override
public void execute() {
// normal fish swim impl
}
}
public class Fish {
private final SwimStrategy swimStrategy;
public Fish(SwimStrategy swimStrategy) {
this.swimStrategy = swimStrategy;
}
public void swim() {
swimStrategy.execute();
}
}
In order to instantiate an object you could do:
new Fish(new FatFishSwimStrategy());
or for the normal behavior:
new Fish(new FishSwimStrategy());
I think it can do by extends and factory method:
public class Unit {
public static Unit createUnit(UnitType type) {
if (UnitType.Special == type) {
return new Unit(type) {
#Override
public int swim() {
System.out.println("special swim");
return 0;
}
};
}
return new Unit(UnitType.Default);
}
private UnitType type;
private Unit(UnitType type) {
this.type = type;
System.out.println("create unit for " + type);
}
public int swim() {
System.out.println("default swim");
return 0;
}
public static void main(String[] args) {
Unit fish = Unit.createUnit(UnitType.Default);
Unit fatFish = Unit.createUnit(UnitType.Special);
fish.swim();
fatFish.swim();
}
}
This is a simple type enum:
public enum UnitType {
Default, Special
}
There are two ways to accomplish this polymorphic behavior in Java. The first is to use a inheritance and a hierarchical set of classes. For example, you could have an abstract base class which defines an abstract method called "swim". Then each concrete fish class would extend this base class and implement the swim method. Later when you have a set of fish objects, you can upcast them to the base class and invoke the swim method on each.
The second way is to use interfaces. You define an interface (e.g. ISwim) which declares the public method swim. Each fish class (whether part of a class hierarchy or no) would implement the ISwim interface, meaning they would define a swim method. Then if you have a set of fish class objects of different types, you can cast each to the ISwim interface and invoke the swim method on each object.
Java does not have function pointers, so the approach you are considering is inappropriate for the language. Even in languages with function pointers, the above two approaches would be most appropriate in my opinion.
One way to do this is with an enum for the types of Unit and with Unit subclasses:
public class Unit {
public enum UnitType {
REGULAR {
public Unit makeUnit() {
return new RegularUnit();
}
},
SPECIAL {
public Unit makeUnit() {
return new SpecialUnit();
}
};
abstract public Unit makeUnit();
}
protected Unit() {}
public abstract int swim();
private static class RegularUnit extends Unit {
RegularUnit() {}
public int swim() {
return 0;
}
}
private static class SpecialUnit extends Unit {
SpecialUnit() {}
public int swim() {
return 1;
}
}
}
Unit fish = UnitType.REGULAR.makeUnit();
Unit fatFish = UnitType.SPECIAL.makeUnit();
Another way is with Callable objects:
public class Unit {
public enum UnitType { REGULAR, SPECIAL }
private Callable<Integer> additionFunc;
public Unit(UnitType type) {
switch (type) {
case REGULAR:
additionFunc = new Callable<Integer>() {
public Integer call() {
return 0;
}
};
break;
case SPECIAL:
additionFunc = new Callable<Integer>() {
public Integer call() {
return 1;
}
};
break;
}
}
public int swim() {
return additionFunc();
}
}
Using a simple if statement:
private String unitType;
public Unit(unitType) {
this.unitType = unitType;
}
public int swim() {
if (unitType.equals("specialType") {
return specialFunc();
}
else {
return regularFunc();
}
}
Or using polymorphism and a factory method :
public abstract class Unit() {
protected Unit() {
}
protected abstract int addition();
public int swim() {
return addition();
}
public static Unit forType(String unitType) {
if (unitType.equals("specialType") {
return new SpecialUnit();
}
else {
return new RegularUnit();
}
}
private static class SpecialUnit extends Unit {
#Override
protected addition() {
// special addition
}
}
private static class RegularUnit extends Unit {
#Override
protected addition() {
// regular addition
}
}
}
Or using an Adder functional interface, defining an addition() method, and two concrete implementations of this interface:
private Adder adder;
public Unit(unitType) {
if (unitType.equals("specialType") {
this.adder = new SpecialAdder();
}
else {
this.adder = new RegularAdder();
}
}
public int swim() {
return adder.addition();
}
This last one is the closest to waht you asked in your question. function objects don't exist per se, but can be replaced by interfaces.

Categories

Resources