I have a doubt in my code :
public abstract class Jogador {
String nome;
int pontos;
Jogador (String n) {
nome = n;
}
void aumentaPontos () {
pontos++;
}
abstract <U extends Jogador> boolean melhor (U outro);
}
class JogadorAdivinha extends Jogador {
JogadorAdivinha (String n) {
super(n);
}
boolean melhor (JogadorAdivinha outro) {
if (this.pontos > outro.pontos)
return true;
return false;
}
}
class JogadorMemoria extends Jogador {
int rodadasGanhas;
JogadorMemoria(String n) {
super(n);
}
boolean melhor(JogadorMemoria outro) {
if (this.rodadasGanhas > outro.rodadasGanhas)
return true;
return false;
}
void aumentaRodadasGanhas() {
rodadasGanhas++;
}
}
I'll have compilation problem at both the child classes of Jogador.
But as you can see, only JogadorMemoria has rodadasGanhas.
So, I want to know a way to handle this situation .... if I put as parameter the class Jogador for the method melhor() , I won't be able to receive the children ...
What can I do about it to override the abstract method and to not create a bad smell ??
If you want to implement a method like this in subclasses:
abstract <U extends Jogador> boolean melhor (U outro);
You have to provide override-equivalent implementations, like:
<U extends Jogador> boolean melhor (U outro) { return true; }
You can't drop type variables in subclasses, as the abstract method's declaration says that it has to be able to accept any instance of Jogador as a parameter to the melhor method.
If you want to have specific parameter types on those methods, you define the type variable at class-level:
public abstract class Jogador<U extends Jodador<U>> {
abstract boolean melhor (U outro);
}
and then you can implement this in the subclasses:
class JogadorAdivinha extends Jogador<JogadorAdivinha> {
boolean melhor (JogadorAdivinha outro) { return true; }
}
Related
How can I create abstract generic method doSomething() that accepts different enums? Enum1 and Enum2, Enum3 and so on?
public abstract class NumerOne {
public abstract void doSomething();
}
public class NumberTwo extends NumberOne {
#Override
public void doSomething (Enum1 enum1) {
enum1.createSomething();
}
The most appropriate way to accept a handful of Enum types, but not accept any enum (<T extends Enum<T>) or (even worse) Object would be to create an interface and have all the enums that you want to accept implement that interface:
interface CreatorOfSomething {
// I have no idea what type should be returned here,
// as you don't use this value in your example.
// But I'm pretty sure it can't be void, so I'll go with Integer.
// You can have this parameterised as <T> at the interface level.
Integer createSomething();
}
enum Enum1 implements CreatorOfSomething {
A, B, C;
#Override
public Integer createSomething() {
return ordinal();
}
}
enum Enum2 implements CreatorOfSomething {
X { // you can override the method for individual constants
#Override
public Integer createSomething() {
// .....
}
},
Y { ....
}
Then your method would look like:
public void doSomething(CreatorOfSomething creator) {
creator.createSomething();
}
The code you posted does not even compile. Nor could we run it. Next time please provide an SSCCE in which you address your question.
Here's the solution for the problem you have:
abstract class NumberOne {
public abstract <T extends Enum<T>> void doSomething(T pEnum);
}
enum Enum1 {
A, B
}
enum Enum2 {
C, D
}
public class NumberTwo extends NumberOne {
#Override public <T extends Enum<T>> void doSomething(final T pEnum) {
System.out.println("Value: " + pEnum);
}
public static void main(final String[] args) {
final NumberTwo n2 = new NumberTwo();
n2.doSomething(Enum1.A);
n2.doSomething(Enum2.D);
}
}
The below get method given Sonar issue:
Generic wildcard types should not be used in return types.
I need some expert help to refactor this code to avoid that Sonar issue. I try different ways like Entity<D.Id> but I haven't idea how to combine with Entity<C.Id>.
public interface Identity {
//
}
public interface Entity<I extends Identity> {
//
}
public interface D
extends Entity<D.Id>
{
}
public interface C
extends Entity<C.Id>
{
}
protected Entity<? extends Identity> get(final String value)
{
if (value == 'valuD')
{
return new D() //return object;
}
else
{
return new C() //return object;
}
}
public class ClassX<T> implements Comparable<ClassX<T>> {
private T o;
public ClassX(T o) {
this.o = o;
}
public T getObject() {
return o;
}
public void setObject(T o) {
this.o = o;
}
#Override
public int compareTo(ClassX<T> arg0) {
return o.compareTo(arg0.o);
}
}
If I have a class like this and I want to implement the Comparable interface, I read that I have to change ClassX<T> to ClassX<T extends Comparable<T>>. But what if I also want to use my ClassX for objects that don't implement the Comparable interface, knowing that I would not be able to use the method compareTo() for those objects?
Another option is, instead of implementing Comparable, have a static method that returns a Comparator, and this method can only be called when the constraint on T is met. So then your ClassX can be used with T that do not implement Comparable, but you can only obtain Comparators for ClassXs with T that do implement Comparable.
public class ClassX<T> {
private T o;
// ...
public static <T extends Comparable<? super T>> Comparator<ClassX<T>> getComparator() {
return (x, y) -> x.o.compareTo(y.o);
}
}
How about creating another layer of hierarchy to support this:
public class NonComparableClassX<T> implements Comparable<NonComparableClassX<T>> {
// ....
#Override
public int compareTo(ClassX<T> arg0) {
// throw Exception;
}
}
public class ClassX<T> extends NonComparableClassX<T> {
// ....
#Override
public int compareTo(ClassX<T> arg0) {
// Implement comparables here
}
}
This way you can encapsulate all objects as ClassX, which can also be of the type NonComparableClassX if need be
I have a Super class and some Sub class that extend the super class. Every sub class have some constructor methods that accept a type of any Sub type.
abstract class Super {}
final class Sub1 extends Super {
public Sub1(Sub1 arg) {}
//...
public Sub1(Sub4 arg) {}
}
//...
final class SubN extends Super {
public SubN(Sub3 arg) {}
//...
public SubN(SubN arg) {}
}
}
Now I want to create a method in the Super class to cast from one Sub type to another. Let's say
public Super cast(Super arg) {
if (arg instanceof Sub1) {
return new Sub1(this);
} else if (arg instanceof Sub2) {
return new Sub2(this);
}//...
return null;
}
It would be stupid to repeat this pattern for all the sub classes. A solution that I found out is this one (using reflection) but is too slow.
public Super cast(Super arg) {
try {
Class<? extends Super> type = arg.getClass();
return type.getConstructor(this.getClass()).newInstance(this);
} catch (Exception e) {
return null;
}
}
Are there alternatives?
Why not do the reverse? Instead of super.cast(sub) do sub.copy(super) Example:
class Sub1 extends Super {
public Super copy(Super input) {
return new Sub1(input);
}
}
class Sub2 extends Super {
public Super copy(Super input) {
return new Sub2(input);
}
}
etc.
This is called in nearly the same way and prevents having any if statements, and gets exactly the same functionality.
If your old code was:
void doSomething(Super super, Super iAmActuallyASub) {
Super superDuper = super.cast(iAmActuallyASub);
}
The new code would be
void doSomething(Super super, Super iAmActuallyASub) {
Super superDuper = iAmActuallyASub.copy(super);
}
In the following code sample, is there a way to avoid the ugly SuppressWarnings annotations?
The code tests if parameter t is an instance of A and returns another instance of A if so. That satisfies the general contract of createCopy() to return an object of the same type as its parameter, so it is a safe operation. The same goes for the test for B.
I know about Wildcard Capture and Helper Methods but I'm not sure if and how that helps in this situation although the problem appears to be quite similar.
abstract class Base {
public static <T extends Base> T createCopy(T t) {
if (t instanceof A) {
#SuppressWarnings("unchecked")
T copy = (T) new A((A) t);
return copy;
}
if (t instanceof B) {
#SuppressWarnings("unchecked")
T copy = (T) new B((B) t);
return copy;
}
throw new IllegalStateException();
}
}
class A extends Base {
public A() { }
public A(A a) { }
}
class B extends Base {
public B() { }
public B(B b) { }
}
You can pass the class to the method, but that's still ugly:
abstract class Base {
public static <T extends Base> T createCopy(final T t,
final Class<T> klass) {
if (t instanceof A) {
final T copy = klass.cast(new A((A) t));
return copy;
}
if (t instanceof B) {
final T copy = klass.cast(new B((B) t));
return copy;
}
throw new IllegalStateException();
}
}
class A extends Base {
public A() {
}
public A(final A a) {
}
}
class B extends Base {
public B() {
}
public B(final B b) {
}
}
Calling t.getClass() doesn't work either. The reason is that T can be a subtype of A or B (that's why you code is not really type-safe).
EDIT :
Why your code is not really type-safe: imagine a class AA that extends A. If you call your method with an instance of this class, it will create an object of type A and try to cast it to AA.