Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding Java generic methods

I wanted to create an interface for copying an object to a destination object of the same class. The simple way is to use casting:

import org.junit.Test;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.RunWith;

@RunWith(JUnit4ClassRunner.class)
public class TestGenerics {
public static interface Copyable {
    public void copy(Copyable c);
}

public static class A implements Copyable {
    private String aField = "--A--";
    protected void innerCopy(Copyable c) {
        A a = (A)c;
        System.out.println(a.aField);
    }
    public void copy(Copyable c) {
        innerCopy(c);
    }
}

public static class B extends A {
    private String bField = "--B--";
    protected void innerCopy(Copyable c) {
        B b = (B)c;
        super.innerCopy(b);
        System.out.println(b.bField);
    }
}

@Test
public void testCopy() {
    Copyable b1 = new B();
    Copyable b2 = new B();
    b1.copy(b2);
}
}

But also i've found a way it can be done using generics:

import org.junit.Test;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.RunWith;

@RunWith(JUnit4ClassRunner.class)
public class TestGenerics {
    public static interface Copyable<T> {
        public void copy(T t);
    }

    public static class A<T extends A<?>> implements Copyable<T> {
        private String a = "--A--";
        public void copy(T t) {
            System.out.println(t.a);
        }
    }

    public static class B<T extends B<?>> extends A<T> {
        private String b = "--B--";
        public void copy(T t) {
            super.copy(t);
            System.out.println(t.b);
        }
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testCopy() {
        Copyable b1 = new B();
        Copyable b2 = new B();
        b1.copy(b2);
    }
}

Though the only way i've found to get rid of warnings is the annotation. And it feels like something is wrong. So what's wrong? I can accept that something is wrong in the root of the problem. So any sort of clarification is welcome.

like image 504
Oleg Galako Avatar asked Sep 19 '26 11:09

Oleg Galako


2 Answers

Your interface definition:

public interface Copyable<T extends Copyable<T>> {
    void copy(T copyFrom);
}

Your implementation:

public class Example implements Copyable<Example> {
    private Object data;
    void copy(Example copyFrom) {
        data = copyFrom.data;
    }
    //nontrivial stuff
}

That should take care of your warnings.

like image 92
wowest Avatar answered Sep 22 '26 01:09

wowest


Assuming you don't want to subclass further you just need:

public static /*final*/ class AClass implements Copyable<AClass> {

For an abstract class, you do the "enum" thing:

public static abstract class AClass<T extends AClass<T>> implements Copyable<T> {
like image 41
Tom Hawtin - tackline Avatar answered Sep 22 '26 00:09

Tom Hawtin - tackline



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!