Visitor pattern with two method parameters - java

I have a class MethodClass and classes Foo and Bar that both extend FooBar. MethodClass has a list containing objects of Foo and Bar and a method doMethod() that picks two random elements out of this list and passes them to doMethod(FooBar fooBar1, FooBar fooBar2). The result of doMethod(FooBar fooBar1, FooBar fooBar2) depends on the subclasses of the given arguments.
The structure thus far:
Class MethodClass:
List<Foobar> list;
void doMethod() {
FooBar obj1 = ...;
FooBar obj2 = ...;
doMethod(obj1,obj2);
void doMethod(FooBar fooBar1, FooBar fooBar2) {
//instance checking and downcasting
...
}
void doMethod(Foo foo1, Foo foo2) {
foo1.doA();
foo2.doA();
}
void doMethod(Foo foo, Bar bar) {
foo.doB();
bar.doB();
}
void doMethod(Bar bar1, Bar bar2) {
bar1.doA();
bar2.doA();
}
Abstract Class FooBar:
public abstract class FooBar {
abstract void methodA() {...}
abstract void methodB() {...}
}
Class Foo:
public class Foo extends FooBar {
void methodB() {...}
void methodB() {...}
}
Class Bar:
public class Foo extends FooBar {
void methodA() {...}
void methodB() {...}
}
I will further extend FooBar in the future (The subclasses will only have methodA and methodB). Is it possible to achieve this without donwcasting and without the need of updating more than one class when adding a subclass to FooBar? If doMethod took only one argument this would be easily done using a variant of a visitor pattern but I can't find a proper way to scale it up to two arguments.
Thanks in advance.

I will further extend FooBar in the future.
So the visitor pattern is not the best choice as it is designed to define new operations without changing the model and not the reverse.
Besides, actually you invoke different methods according to the specific subclass of the parameter such as :
void doMethod(Foo foo1, Foo foo2) {
foo1.doA();
foo2.doA();
}
void doMethod(Foo foo, Bar bar) {
foo.doB();
bar.doB();
}
It is like whether according to the subclass of the elements picked from the list you would perform a distinct operation.
So polymorphism (base of the visitor pattern but also of the most of design patterns) will not be helpful here.
To benefit from the polymorphism, you should provide a higher abstraction level.
Your requirement is broad and very abstract. So I cannot give you more specific pointers but anyway I think that you should review the overall design and focus on the consistency between the behaviors defined by the subclasses.

Related

Creating an intance of a Class via method of an Interface implemented by that class

I want to call the constructor of a class inside the method of an interface.
For example, if I have two classes B and C and they both implement SomeInterface, so that each of them has method foo().
interface SomeInterface {
public SomeInterface foo();
}
class B implements SomeInterface {
public B(int fst, int snd) {}
#Override
public SomeInterface foo() {
return new B(1, 1);
}
}
class C implements SomeInterface {
public C(int fst, int snd) {}
#Override
public SomeInterface foo() {
return new C(1, 1);
}
}
And let's say, for the sake of this question, that I have a lot more classes that implement SomeInterface and they all do the same thing, that is return new <nameoftheclass>(1,1)
and all these classes extend the parent class A.
Is there a way for me to create only one method in A such that if any of these classes use the foo method that is found in A it will call their constructor and just like that save me lines of code?
You can do something like this with reflection, although it will be prone to failure.
public SomeInterface foo() {
Constructor<? extends SomeInterface> c = getClass().getConstructor(int.class, int.class);
return c.newInstance( 1, 1);
}
You'll have to manage some exceptions, but is this what you're after?
The question would then be, where can this be used? Interfaces don't have a common constructor.
public interface SomeInterface{
default SomeInterface another(){
Constructor<? extends SomeInterface> c = getClass().getConstructor(int.class, int.class);
return c.newInstance( 1, 1);
}
}
That would work provided whatever the implementations try to use it have that constructor. There is no guarantee that constructor exists though. Maybe you would want it on an abstract class?
use the foo method that is found in A it will call their constructor and just like that save me lines of code?
You are getting it wrong. Class design decisions must be based on use cases and relationships of the classes in your domain. If your main criteria will be to spare some lines of code, you can end up with a coffee machine extending combine harvester because both of them have tree dimensions. Don't take a pill if you have no headache.
Parent class A that you've mentioned doesn't make any sense because method foo() returns an instance of SomeInterface interface which A doesn't implement (because if it does, its subclasses don't need to declare to implement it). I.e. A and SomeInterface are not compatible and compiler will not allow to type cast between them. Therefore, I'll omit the parent class.
As an example, the "template" you've provided might be useful, will be a situation when classes with similar functionality need to grouped together.
The interface can serve as a single entry point for the user of the code. Every class will implement the behavior defined by the interface, and only through the interface it'll be possible to get an instance of the class with a particular flavor of functionality. The actual classes will be hidden from the user.
Similarly, abstract class NumberFormat from the JDK provides a way to obtain different kinds of formatters, but actual implementations are hidden are not exposed (the approach shown below is far more simple than the actual way of how factory methods of the NumberFormat are implemented).
Note, interface and its implementations must reside in the same package.
public interface BaseInterface {
public static BaseInterface getInstance(Classifier classifier) { // factory
return switch(classifier) {
case A -> new A();
case B -> new B();
};
}
void doSomeThingUseful(); // behaviour that every class should implement
}
enum Classifier { A, B }
class A implements BaseInterface {
A() {}
#Override
public void doSomeThingUseful() {
System.out.println("Class A");
}
}
class B implements BaseInterface {
B() {}
#Override
public void doSomeThingUseful() {
System.out.println("Class B");
}
}
main() - demo
public static void main(String[] args) {
List<BaseInterface> items = List.of(BaseInterface.getInstance(Classifier.A),
BaseInterface.getInstance(Classifier.B));
for (BaseInterface item: items) {
item.doSomeThingUseful();
}
}
Output
Class A
Class B

Change behavior without modifying base class

I have a class, let's call it A with a method foo(/*with some params*/) . I'm already using that class in my code. Now in case some param bar, that I pass to the above method, has a specific value I'd like my foo() method to return a slightly different result.
Obviously I could create a class B and copy the foo method's code, alter it a bit to fit my needs and at runtime check the value of bar and decide which class to call.
Is it possible using some design pattern to make that change with the following requirements in mind: a) keep using A in my code (probable use an InterfaceA and use that instead of A) so I won't have to change it
and b) don't modify the code of class A cause it's possible to later have a class C with an altered foo() and the another and then another...
You could define B which would extend the interface that A implemented and have A (or better, the interface type) as a field.
interface AbstractA {
void foo(Object o);
}
class A implements AbstractA {
#Override
public void foo(Object o) {}
}
class B implements AbstractA {
private AbstractA abstractA;
#Override
public void foo(Object o) {
abstractA.foo(o);
// "a slightly different result"
}
}
It's an example of the decorator pattern, which, as Wikipedia puts it,
allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.
class Base{
foo(param1, param...n){
// code
}
}
class child1 extends Base{
bar(param1, param2, param...n){
super.foo(param1, param2);
// specifi code related for child1
}
}
class child2 extends Base {
bar(param1, param2, param...n){
super.foo(param1, param2);
// specifi code related for child2
}
}
Base ob1 = new child1();
ob1.bar(param1,param2,param..n);
ob1 = new child2();
ob1.bar(param1,param2,param..n);

Extending interfaces changing method signature

Consider the following interfaces
interface Foo1
{
public function foo(BaseClass)
}
and
interface Foo2
{
public function foo(SpecialClass)
}
where SpecialClass inherits from BaseClass.
Now, a Foo1 instance could be used whenever a Foo2 instance is required. I mean, if I need an object with a foo method that accepts a SpecialClass, I could do the job with an object with a foo method that accepts a BaseClass.
Hence I would like to be able to declare Foo1 as a sublclass of Foo2 (i.e. Foo1 extends Foo2).
In PHP (the language I usually work with) this is not possible and would produce a fatal error.
As far as I know this is feasible in Java, but would require to implement a specific foo method taking a special class as argument (am I wrong on this?).
Does all this make sense or am I missing something? Is there any other object oriented language that provides this out of the box?
In java syntax the interface should be declared as following:
interface Foo2
{
public void foo(SpecialClass b);
}
interface Foo1 extends Foo2
{
public void foo(BaseClass s); // In Java doesn't inherits from Foo2.foo!
}
The above script is theoretically correct from inheritance perspective. Unfortunately, Java don't interprets it in the expected way: Foo1.foo and Foo2.foo are considered two different overloaded functions.
The only declaration accepted and interpreted by Java in the expected way is the following:
interface Foo2
{
public void foo(BaseClass b);
}
interface Foo1 extends Foo2
{
public void foo(BaseClass b);
}
And then you can write in your own implementation something like:
class Foo1Class implements Foo1
{
public void foo(BaseClass b)
{
if(!(b instanceof SpecialClass)) throw new ClassCastException();
...
}
}

A class inheriting methods from two sources

It's hard to explain, but it's simple to show a snippet of Ruby code:
Have two modules that implement methods:
module Foo
def one
print "ONE!"
end
end
module Bar
def two
print "TWO!"
end
end
Have a class that includes them:
class Test
include Foo
include Bar
end
Now your class Test can call those two methods.
As far as I'm aware, there isn't something like this in Java. Close concepts would be:
Multiple inheritance
Which is not supported by Java.
Interfaces
They're method contracts - there is no implementation. Your class Test would need to implement the methods itself, and that's what I want to avoid. Simply for the sake of not writing the same code twice (I have several other classes, some of them may want to implement those methods too).
Abstract classes
I'd still need to inherit from two classes at the same time.
So what is the recommended solution here?
In Java 8 you could achieve this using default methods but that was never the intent of defaults so this may be bad advice:
interface Foo {
default void one () {
System.out.println("ONE!");
}
}
interface Bar {
default void two () {
System.out.println("TWO!");
}
}
class FooBar implements Foo, Bar {
}
public void test() {
FooBar fooBar = new FooBar();
fooBar.one();
fooBar.two();
}
However, I would like to reiterate what #Thomas said in his comment The need for multiple inheritance is often a sign of a flaw in the design.
The easiest solution is to create hierarchical inheritance as so :
public class foo
{
public void one()
{
System.out.println("ONE!");
}
}
public class bar extends foo
{
public void two()
{
System.out.println("TWO!");
}
}
class Test extends bar
{
//this class now has access to both methods from the two classes
}
Favour composition over inheritance. So your class would have references to both implementing classes.
MyClass {
ClassA
ClassB
}
Th alternative of subclassing twice, seems rather hacky to me and would lead to an unnecessarily complex inheritance tree.
Or with java 8's new static methods (as opposed to default which can be overridden). See comparator for examples.
interface X
{
static void foo()
{
System.out.println("foo");
}
}
interface Y
{
static void bar()
{
System.out.println("bar");
}
}
MyClass implements X, Y {
public static void main(String args[])
X.foo();
}
The interface name must be used as prefix, as static method is part of interface.
There are few solutions that might solve your case. You can use the Visitor Pattern or Strategy Pattern.
In both cases you will benefit from Interfaces and Composition.
Your class Test would need to implement the methods itself, and that's what I want to avoid.
Well, yes, but that "implementation" could just be a simple delegation (and your IDE can create the code for this wrapper automatically).
public String one(){
return foo.one();
}
The actual code can be in class Foo, and be shared (as in "used") among many classes.

Java generics - method parameter

Is it necessary to parametrize the entire interface for this scenario, even though Bar is only being used in a single method?
public interface IFoo<T>{
void method1(Bar<T> bar);
//Many other methods that don't use Bar....
}
public class Foo1 implements IFoo<Yellow>{
void method1(Bar<Yellow> bar){...};
//Many other methods that don't use Bar....
}
public class Foo2 implements IFoo<Green>{
void method1(Bar<Green> bar){...};
//Many other methods that don't use Bar....
}
No, it's not necessary from a syntactic standpoint. You can also do this:
public interface IFoo {
<T> void method1(Bar<T> bar);
/* Many other methods that don't use Bar… */
}
Or this:
public interface IFoo {
void method1(Bar<?> bar);
/* Many other methods that don't use Bar… */
}
The correct choice depends on the semantics of IFoo and what its implementations are likely to do with the Bar instances they receive through method1.
I would ask the question a bit differently, because the need suggests a cost, which is not actual. I don't think it actually matter if it is used on only one, or several methods.
When you make several calls to the instance, how does the type parameter vary?:
if constant once you instantiated the instance, you parameterize the entire interface.
if it may be different on each call, you parameterize the method.
That way, the type of parameter actually gives information about the code, improve the meaning and clarity.
Edited: Example
If sometimes, the type parameter varies from call to call, for the same instance ...
It has to be a method parameter.
You're not extending the interface. Is that deliberate? You can do this:
public class Foo2 implements IFoo<Green> {
void method1(Bar<Green> bar);
}
Just doing this:
public class Foo<Green> {
void method1(Bar<Green> bar);
}
won't compile.

Categories

Resources