Say I have a couple of Objects (=classes) which each has a method getX():
public class A{
/* some code */
public float getX(){}
}
public class B{
/* some code */
public float getX(){}
}
Now I want to write a generic static method as the following:
public static <T> boolean isOverlaps(T obj) {
if (obj == null || (!obj.getClass().isInstance(A.class) && !obj.getClass().isInstance(B.class)))
return false;
return obj.getX() >= 0 && /*some logic*/; // here it falls
}
IDE says:
Cannot resolve method 'getX()' in 'T'
How can I resolve the method properly without casting (since it is a generic method)? Is it even possible?
You need an interface to let Java know that T has the desired function:
public interface I {
float getX();
}
public class A implements I {
/* some code */
public float getX(){
return 1.0f;
}
}
public class B implements I {
/* some code */
public float getX(){
return 2.0f;
}
}
public static <T extends I> boolean isOverlaps(T obj) {
return obj.getX() >= 0 && /*some logic*/;
}
Or, a bit simpler without the unnecessary type variable:
public static boolean isOverlaps(I obj) {
return obj.getX() >= 0 && /*some logic*/;
}
Using an interface is the preferred way to solve this, but the statement "you need an interface" is incorrect.
You can achieve this without an interface too. In some situations (i.e. where you can't modify A or B), this may be the best you can do.
public static boolean isOverlaps(Object obj) {
float x = -1;
if (obj instanceof A) {
x = ((A) obj).getX();
}
else if (obj instanceof B) {
x = ((B) obj).getX();
}
return x >= 0 && /*some logic*/;
}
public static <T> boolean isOverlaps(T obj) {
This isn't really a generic method. OK, it is a generic method, because it has a type variable; it's just not a usefully generic method. You can pass anything to it: it's essentially equivalent to:
public static boolean isOverlaps(Object obj) {
That is, you can't access anything inside that method which isn't a method on Object.
If you want to use this, and you can't use the common interface approach, you could do an instanceof chain:
public static boolean isOverlaps(Object obj) {
if (obj instanceof A) {
return /* logic */;
} else if (obj instanceof B) {
// Do something.
return /* logic */;
}
return false;
}
The problem with this is that you're losing the compile-time safety of not being allowed to pass things other than As and Bs to it (e.g. you could call isOverlaps("Hello world!"), which is presumably nonsensical).
It's actually better to define two overloads:
public static boolean isOverlaps(A obj) { return /* logic */; }
public static boolean isOverlaps(B obj) { return /* logic */; }
because now trying to pass in anything other than an A or a B results in a compile-time error; but it's a compile-time error at the call site, not in these methods.
If /* logic */ depends on some property which can be derived from A and B, e.g. a getter, you can consolidate the repeated logic into a helper:
public static boolean isOverlaps(A obj) { return helper(obj.getX()); }
public static boolean isOverlaps(B obj) { return helper(obj.getX()); }
private static boolean helper(SomeType value) {
return /* logic */
}
Related
I have a class MyClass and its super-class MySuperClass.
MySuperClass is from a standard library, so its codes cannot be changed.
As per the user requirement, the method name myMethod() of MyClass cannot be changed as well.
Unluckily, the same name MyClass is already in MySuperClass, and those codes are not what I want. I used #Override to override those codes (Thanks for the help from Matteo NNZ who suggested me for this fix in the case of having various generic types).
However, I need to cast keyInt to type K such that I can call the mySubMethod(). Below is my code:
MyClass
public class MyClass<K,V> extends MySuperClass {
// the name "myMethod" are not allowed to be modified
public boolean myMethod(K key) { // if key is NOT integer, Main.java will call this method
mySubMethod(key);
return false;
}
#Override // This is a fix; To Override myMethod(int index) of MySuperClass.
public boolean myMethod(int keyInt) { // if key is integer, Main.java will call this method
K key = (K) keyInt; // <-- I have error here
mySubMethod(key);
return false;
}
public boolean mySubMethod(K key) {
System.out.println("I want to call this");
return false;
}
}
MySuperClass
public class MySuperClass { // codes of MySuperClass are not allowed to be modified
public boolean myMethod(int index) {
System.out.print("Shouldn't be called.");
return false;
}
}
To call MyClass, in Main.java I will create new instances for either MyClass<Integer, String> or MyClass<String, String>. But currently I got error message "Cannot cast from int to K".
I tried to fix the error by using if(key instanceof Integer){ /** blahblahblah */}, but it doesn't work since KeyInt is already an integer when the method is called. How can I fix this?
Do you want this result?
public class MyClass<K,V> extends MySuperClass {
// the name "myMethod" are not allowed to be modified
public boolean myMethod(K key) { // if key is NOT integer, Main.java will call this method
mySubMethod(key);
return false;
}
#Override // This is a fix; To Override myMethod(int index) of MySuperClass.
public boolean myMethod(int keyInt) { // if key is integer, Main.java will call this method
// K key = (K) keyInt; // <-- I have error here
mySubMethod(keyInt);
return false;
}
public <T> boolean mySubMethod(T key) {
System.out.println("I want to call this");
return false;
}
}
Say that I have a method like this:
public AbstractContractApplication acceptOffer(AcceptedOfferDto dto)
{
// various application stuff
Contract contract; // deeply integrated into the above code
return processedApplication; // also deeply integrated into the above code
}
I would like to refactor my method to sometimes return contract instead of processedApplication based on an argument provided in the AcceptedOfferDto. Ideally something like this:
if (AcceptedOfferDto.getReturnConfig() == 1){
return contract;
}
else {
return processedApplication;
}
Is there a clean way to do this which does not involve copy and pasting the bulk of the code in the function or refactoring a large block of extremely important business logic?
The current line of thinking is to create a class that contains instances of both objects and just select the correct value from that. What other options might be available?
Supposing that Contract and AbstractContractApplication have nothing useful in common to rely on polimorphism and you can't refactor too much things, you could use this:
public interface EitherOne<A, B> {
public default boolean isA() { return false; }
public default boolean isB() { return false; }
public default A getA() { throw new IllegalStateException(); }
public default B getB() { throw new IllegalStateException(); }
public static <A, B> EitherOne<A, B> a(A a) {
return new EitherOne<>() {
#Override public boolean isA() { return true; }
#Override public boolean getA() { return a; }
};
}
public static <A, B> EitherOne<A, B> b(B b) {
return new EitherOne<>() {
#Override public boolean isB() { return true; }
#Override public boolean getB() { return b; }
};
}
}
I really don't recommend anyone using this. It should be used only as a quick and dirty escape hatch hack for complicated situations.
Then, you can try this:
public EitherOne<Contract, AbstractContractApplication> acceptOffer(AcceptedOfferDto dto) {
// various application stuff
AbstractContractApplication processedApplication = ...;
Contract contract = ...; // deeply integrated into the above code
if (AcceptedOfferDto.getReturnConfig() == 1) return EitherOne.a(contract);
return EitherOne.b(processedApplication); // also deeply integrated into the above code
}
Use Polymorphism.
The type of contract (Contract) and processedApplication (?) must be subtypes of AbstractContractApplication.
I'm working on a project where I use Foo which is class that's implemented with an interface, FooExpression, and a separate concrete class called Replacement.
Replacement class uses hashmap:
private Map<Foo, FooExpression> replacementMap;
Replacement class uses put method:
public Expression put(Foo foo, FooExpression exp) {
return replacementMap.put(foo, exp);
}
The Replacement class has a method called get:
public FooExpression get(Foo foo) {
return replacementMap.get(foo);
}
The Foo class has a method, applyReplacement:
#Override
public FooExpression applyReplacement(Replacement r) {
Foo foo = new Foo(name);
FooExpression e = r.get(foo);
return e;
}
The Foo class uses an instance variable:
private String name;
The Foo class uses an equal and hashCode():
#Override
public boolean equals(Object o) {
if (!(o instanceof Foo)) {
return false;
} else {
return name.equals(o);
}
}
#Override
public int hashCode() {
return name.hashCode() + 41;
}
The FooExpression interface uses the applyReplacement method:
FooExpression applyReplacement(Replacement r);
Everytime I used applyReplacement method it returns null, simply because of the "new" instantiation.
I'm just wondering if there's a way to implement the Foo without erasing the existing value from the Replacement class? And I can't use generics for this one.
Your equals() method is wrongly implemented, currently it checks:
if o instanceof Foo
and if name.equals(o)
But o is in this case an instance of Foo. Your name though is an instance of String. This will never return true as a String will never be equal to a Foo.
You have to change your equals method accordingly:
#Override
public boolean equals(Object o) {
if (!(o instanceof Foo)) {
return false;
}
Foo foo = (Foo) o;
return name.equals(foo.name);
}
Which can also be simplified to:
#Override
public boolean equals(Object o) {
return o instanceof Foo && name.equals(((Foo) o).name);
}
I have a Java program with the following classes in it
public class A{
protected String name;
...
#Override
public boolean equals(Object obj){
if(!(obj instanceof A)){
return false;
}
A a = (A)(obj);
return a.name.equals(this.name);
}
}
public abstract class B extends A{
#Override
public boolean equals(Object obj){
return equals2(obj);
}
public abstract boolean equals2(Object obj);
}
public class C extends B{
private String data;
...
#Override
public boolean equals2(Object obj){
if(!(obj instanceof C)){
return false;
}
C c = (C)(obj);
if(c.data.equals(this.data)){
return c.name.equals(this.name);
}else{
return false;
}
}
}
Is there a way to force all classes extending class B to implement their own equals methods without having to use equals2 like the example?
Thanks
The only way I can think of is to throw an exception in Bs equals:
public abstract class B extends A {
#Override
public boolean equals(Object obj) {
throw new UnsupportedOperationException();
}
}
This will ensure that sub-classes of B that fail to override equals will not fallback to A's implementation of equals.
Unfortunately, this will result in run-time exceptions, as opposed to compile time errors, which are preferable.
Off the top of my head, you could have the abstract class B throw an exception in its equal() method:
public abstract class B extends A{
#Override
public boolean equals(Object obj){
throw new UnsupportedOperationException("add your own implementation");
}
public abstract boolean equals2(Object obj);
}
Then, anyone subclass of B which attempted to default to the inherited equals method would not work, forcing them to implement their own version.
I've a situation similar to this.
What if I still want to call constructors conditionally? (Though they said creating separate classes is suggestible)
Requirement structure:
Super class:
public class Super
{
public Super(DTO1 dto1Object){
this.dto1Object = dto1Object;
}
public Super(DTO2 dto2Object)){
this.dto2Object = dto2Object;
}
}
Derived class:
public class Derived extends Super
{
public Derived(Object obj)
{
//some_condition to check if passed object obj is dto1Object
//do something with dto1Object
//some_condition to check if passed object is dto2Object
//do something with dto2Object
}
}
How should I implement it?
EDIT:
Implemented it in this way based on the suggestion below:
Super class:
public class Super
{
protected static DTO1 dto1Obj;
protected static DTO2 dto2Obj;
public Super(DTO1 dto1Object){
this.dto1Object = dto1Object;
}
public Super(DTO2 dto2Object)){
this.dto2Object = dto2Object;
}
}
Derived class:
public class Derived extends Super
{
public Derived(DTO1 dto1Object){ super(dto1Object); }
public Derived(DTO2 dto2Object){ super(dto2Object); }
public static Derived create(Object obj) {
if (obj.equals(dto1Obj) {
return new Derived((DTO1) obj);
}
if (obj.equals(dto2Obj) {
return new Derived((DTO2) obj);
}
// ...
private String Function(String str){
if(create(dto1Obj).equals(dto1Obj) {
//do something
}
else if(create(dto2Obj).equals(dto2Obj)){
//do something else
}
return str;
}
}
}
EDIT2:
As per suggestion below, is this the correct way to use instanceof?
if (create(dto1Obj) instanceof DTO1) {
//something
}
else if(create(dto2Obj) instanceof DTO2) {
//something else
}
Is shows the following error:
Incompatible conditional operand types Derived and DTO1
Incompatible conditional operand types Derived and DTO2
You can't in the constructor, because the super(...) has to be the first statement.
The only way I can think is to use a static factory method, and invoke class-specific overloads of the constructor:
public class Derived extends Super
{
private Derived(DTO1 dto1Object){ super(dto1Object); }
private Derived(DTO2 dto2Object){ super(dto2Object); }
public static Derived create(Object obj) {
//some_condition to check if passed object obj is dto1Object
//do something with dto1Object
if (someCondition) {
return new Derived((DTO1) obj);
}
//some_condition to check if passed object is dto2Object
//do something with dto2Object
if (someOtherCondition) {
return new Derived((DTO2) obj);
}
// ...?
}
}