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.
Related
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
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);
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);
}
}
I have an abstract class where I want to create a method that can be passed either of the child instances that extend it.
For example:
abstract class base
{
public void doSomething(Child1 or Child2){
}
}
class Child1 extends base
{
public void somefunc(){
doSomething(Child1);
}
}
class Child2 extends base
{
public void somefunc(){
doSomething(Child2);
}
}
I feel like there are multiple ways to get around it. Is it possible to get an idea of what are the possible ways? I definitely dont want to create the same function in all the child classes.
I'm not sure if the parameter passed to doSomething is supposed to be this, or a separate object of the same type. In the first case, peter.petrov's answer is what you want. In the second case, the standard way around this is to make Base generic and to use a recursive bound.
abstract class Base<T extends Base<T>> {
public void doSomething(T t) {}
}
class Child1 extends Base<Child1> {
public void someFunc() {
Child1 child1 = new Child1();
doSomething(child1);
}
}
class Child2 extends Base<Child2> {
public void someFunc() {
Child2 child2 = new Child2();
doSomething(child2);
}
}
Seems like this is what you're looking for.
abstract class base
{
public void doSomething(base obj){
}
}
class Child1 extends base
{
public void somefunc(){
doSomething(this);
}
}
class Child2 extends base
{
public void somefunc(){
doSomething(this);
}
}
Then, if you want override doSomething in your child classes.
In fact, you don't even need the base parameter and to pass this, you already have an implicit reference to this.
One of the ideas behind inheritance is to share behaviour amongst classes of the same abstract type.
So if you want the same behaviour for all subtypes of your base class, implement the method in your base class. You don't need to pass the object reference, use the this keyword.
If you want different behaviours in your sub classes, declare the method abstract in your base class and implement each of the behaviours in the various sub classes.
I had a doubt.
Imagine If we have a class A that implements the method
For example
private void methodA(int index) throws Exception, Error {
}
And if we have a Class B that extends the first class A.
My questions is, can class B implement
private void methodA(int index) throws Exception, Error {
}
And which method will be called under which circumstance!!
Thanks
If your methods weren't declared "private", this would just be standard polymorphism. Because they're private, the rules are a bit different. The version in class A can only be called from code that's in class A. The version in class B can only be called from code that's actually written in class B (as opposed to code that class B gets by extending class A).
YES, you can implement the methodA method in class B, but, pay attention, you are not overriding it.
Your method is declared ad private so is not "visible" from extending classes.
If your intention is to make your method overridable, you need to declare it as public.
Just give it a try :)
public class Main {
public static void main(String[] args) {
Base base;
base = new A();
System.out.println(base.doSth());
base = new B();
System.out.println(base.doSth());
}
}
abstract class Base {
public abstract String doSth();
}
class A extends Base {
#Override
public String doSth() {
return "A";
}
}
class B extends A {
#Override
public String doSth() {
return "B";
}
}
I think you wonna override the super-class method, and to do this, the method on sub-class must have the same signature of super-class method.
You can call these methods in following ways:
Suppose test1 is an instance of classA, teste1.methodA(index) will execute the implementation on super-class.
Suppose test2 is an instance of classB, test2.methodA(index) will execute the sub-class method.
In classB you can invoque the super class method (if the method is notprivate), something like :
public class ClassB extends ClassA
{
...
super.methodA(index);
...
}