Change behavior without modifying base class - java

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);

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

Is there a way to return current class type in a final method?

I have the following situation in java; There is a class that implements a method that is meant to be final but I need the returning type of such method to be exactly that of the class that it calling it. Since I want the method to be final I can't modify the return data type in the subclasses since that would be illegal.
Is there a way to archive this without sacrificing finality and having to override such method for all subclasses that implement it?. Even if the method was not final it would still be faster to implement it this way.
The code would be something like this:
class Parent
{
public currentClass finalMethod() {...}
}
class Children extends Parent {}
public static void main(String args[])
{
Children c = new Children();
System.out.print(c.finalMethod().getClass().getName()); // Would print Children
}
Tried to use reflection and generics to no avail. Examples:
class Parent
{
public this.getClass() finalMethod() {...} //Many Errors
public <extends Parent> finalMethod() {...} // Returns Parent even if called by Child
public Class<? extends Parent>[] getVecinos() // Returns Class<? extends Parent> thus can't use polymorphism which is the use case
}
I know I could use casting but still not the best solution.
The default behavior is that you'll get what you're looking for, as long as finalMethod does not generate new instances using other types.
To use your code:
class Parent {
public final Parent finalMethod() {
return this;
}
}
With that, c.finalMethod().getClass().getName() returns Children. That's because this inside finalMethod() is the same object that was created using new Children() and getClass() returns the runtime class of the object.
That uses inheritance and as long as you can work with Parent as the return type, you should be fine. If, however, your objective is to call methods specific to Children on the return value of finalMethod(), you may need to make Parent generic. Something like this:
class Parent<C extends Parent<C>> {
public final Parent<C> finalMethod() {
//whatever
return this;
}
}
class Children extends Parent<Children> {
}
And that would make the following code valid, still producing the same output:
Parent<Children> c = new Children(); //or Children c = new Children();
System.out.print(c.finalMethod().getClass().getName());
This has the advantage of allowing you to make static reference to Child-specific methods without prior casting. But it's not the right solution unless it's okay to make Parent generic. It's also not fail-safe.

Working with some childclass of on a class hierrarchy

Imagine this scenario:
public class A {
...
}
class B extends A {
public foo getFoo() {
returns _foo;
}
}
there also exist other classes children of A having the same method
class C extends A {
...
public foo getFoo() { returns _foo; }
...
}
So, the method `foo` doesn't exist in parent class, however, it exists in all children classes.
Is there a way in Java to not directly specify which child class will be called however use a generic way (I believe in Scala it's [T < A]).
So that I can use it like this:
void Bar(`[some child class of A]` childOfA){
childOfA.getFoo(); // Now this would return either getFoo() of A or B
}
That won't be possible with current setup because there is no guarantee that the method will be present in subclasses until unless it's mandated.
Now, what you can do, change parent class, and add abstract method there. That will insure, the method is always present in child class or it's further child classes (in case of child class is abstract).
abstract class A {
public abstract Foo getFoo();
}
class C extends A {
public Foo getFoo(){
// your code
}
}
Now, you can have your generic method with an upper bound.
void <T extends A> bar(T childOfA){
childOfA.getFoo();
}
Here, <T extends A> will make sure, your argument should be subclass of A.

Visitor pattern with two method parameters

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.

Using method that return MyClass object within MyClass when MySubClass extends MyClass

I have trouble subclassing a very simple class that has methods returning the initial class too.
public class MyClass {
public MyClass(){
}
public MyClass filterOn(String something){
MyClass result=new MyClass();
result.doSomethingUsingThisInstance(this, something);
return result;
}
}
public class MySubClass extends MyClass{
....
}
Ok, now if I want to call this:
MySubClass subClass=new MySubClass();
MySubClass subClass2=(MySubClass)subClass.filterOn("Hello World");
Then I have a java.lang.ClassCastException:cannot cast MyClass to MySubClass
How to prevent this?
Override the filterOn() method to create the instance you wish in MySubClass :
public class MySubClass extends MyClass{
public MyClass filterOn(String something){
MySubClass result = new MySubClass();
result.doSomethingUsingThisInstance(this, something);
return result;
}
....
}
You could also avoid duplication in filterOn() method by introducing a method in MyClass to create a instance of the current class that we override in subclass:
public class MyClass {
public MyClass(){
}
public MyClass createSpecificInstance() {
return new MyClass();
}
public MyClass filterOn(String something){
MyClass result = createSpecificInstance();
result.doSomethingUsingThisInstance(this, something);
return result;
}
}
Now Sub class only override createSpecificInstance() :
public class MySubClass extends MyClass {
public MyClass createSpecificInstance() {
return new MySubClass();
}
}
(MySubClass)subClass.filterOn("Hello World");
and
public MyClass filterOn(String something)
You can not cast base class to derived class. if you do, you'll get that exception, ClassCastException
Read this: java.lang.ClassCastException
You try to cast your return value to a derived type, which does not work and results in the class cast exception.
Reason: Casting upwards in the type hierarchy works, since your base class requires only attributes/ methods the derived class (trivially) has. The other way around does not work since it may result in problems. Consider:
class Base {
// some stuff here
}
class Derived1 extends Base {
private int foo;
}
class Derived2 extends Base {
private String bar;
}
Base myObject = new Derived1();
// this works, Derived1 has everything Base requires
// myObject.foo still exists, but can not be trivially accessed.
Derived2 myOtherObject = (Derived2)myObject;
// Now what?
// What happens to myObject.foo?
// Where does myOtherObject.bar come from?
What can you do in your situation:
If the implementations of filterOn() are very different depending on the concrete implementation of the derived class, make it abstract in the base class and re-implement it in the derived class.
Check if you have a design problem. Do you really need to cast the result of filterOn() to the derived class?
Use Generics. Remember you can use a derived class as generic in a base class. This only works if the implementation of filterOn() is exactly the same for each subclass (except the types of course).
Provide a constructor that allows creating a derived class instance from the base class. Use it instead of the cast. Something in the line of
Derived1(Base baseObject){
// copy all the stuff from the base object
this.foo = 0; // initialize the rest
}
Maybe inheritance is not what you need. Composition has the tendency to beat inheritance a lot (Explained nicely here). So you can try that:
class BetterThenDerived {
private Base myBaseObject;
private int foo;
}
This is a side of the problem of covariance. See for example Covariance and contravariance. And Demonstrate covariance and contravariance in Java?. It’s not really where Java excels, but there are a couple of options.
First, when overriding a method, you are allowed to declare a more specific return type. For example, in MySubClass you may declare:
#Override
public MySubClass filterOn(String something) {
// ...
}
Now this doesn’t solve your problem. You still need a way for this method to create and do something to a MySubClass object. What it does do, it frees the client code from needing a cast at all. You may take the implementation of the method form davidxxx’s answer (provided that result.doSomethingUsingThisInstance() is protected or public):
#Override
public MySubClass filterOn(String something) {
MySubClass result = new MySubClass();
result.doSomethingUsingThisInstance(this, something);
return result;
}
You may be annoyed to have to duplicate this method in all you subclasses. If the real work stays in result.doSomethingUsingThisInstance() I should think you may be able to live with it.
The other idea is to clone() for producing an object of the correct runtime type:
public class MyClass implements Cloneable {
public MyClass filterOn(String something) {
try {
MyClass result = (MyClass) this.clone();
result.doSomethingUsingThisInstance(this, something);
return result;
} catch (CloneNotSupportedException cnse) {
throw new AssertionError(cnse);
}
}
}
I’d think twice before using this idea, though. One reason your clone contains data that you don’t want to be in there, so you may have to make sure it’s cleared before working on the clone. You may still combine it with returning the specific subtype in the subclass, now it just requires a cast (still inside the implementation, nothing the client needs to worry about):
public class MySubClass extends MyClass {
#Override
public MySubClass filterOn(String something) {
return (MySubClass) super.filterOn(something);
}
}

Categories

Resources