I need to have two methods, one that receives an extension of an abstract class (A) and another that extends this same class and extends an interface (B), like follows:
public class MyClass {
public static void main(String args[]) {
method(new C());
}
public static <T extends A & B> void method(T t) {
// some method
}
public static void method(A a) {
// some method
}
abstract static class A{
}
interface B{
}
static class C extends A{
}
static class D extends A implements B{
}
}
However I'm getting an error saying that they clash
/MyClass.java:10: error: name clash: method(A) and <T>method(T) have the same erasure
public static void method(A a) {
^
where T is a type-variable:
T extends A,B declared in method <T>method(T)
Do anyone knows a work around and what is the reason of this behavior?
Related
Here is the following code
public abstract class A {
public abstract <E> void foo(E e);
}
the subclass:
public class B extends A {
#Override
public <OtherClass> void foo(OtherClass oc) {
oc.someOtherClassMethod(); //here compiler cannot see method
}
}
and class with main
public class C {
public static void main(String[] args) {
OtherClass oc = new OtherClass();
A a = new B();
a.foo(oc);
}
}
the error I get:
error: cannot find symbol
...
symbol: method someOtherClassMethod()
location: variable oc of type OtherClass
where OtherClass is a type-variable:
OtherClass extends Object declared in method <OtherClass>write(OtherClass )
1 error
Why cannot I use the someOtherClassMethod()? Without generics everything works, but I would like to be able to extend other classes in which I override foo() method
Solution:
public abstract class A <E> {
public abstract void foo(E e);
}
Subclass:
public class B extends A<OtherClass> {
#Override
public void foo(OtherClass oc) {
oc.someOtherClassMethod();
}
}
However, now I need use in main function:
A<OtherClass> a = new B();
try
public abstract class A<E> {
public abstract void foo(E e);
}
and
public class B extends A<OtherClass>
I have a scenario that i want to create one support class called D which contains a generic method. I have set the upper bound for type variable.
class A{
void show(){
System.out.println("Hello A");
}
}
class B extends A{
void msg(){
System.out.println("Hello B");
}
}
class C extends A{
void msg(){
System.out.println("Hello C");
}
}
class D{
<T extends A> void display(T ob){
ob.msg(); //here i want to do some tricks
}
}
First i want to share my objective. Here msg() function of B and C class has different implementations. I want to create one support class called D that has one display method, using display method i want to call either msg() function of B or C class dependent on instantiation. Can you tell me how can i achieve it?
You need to have the method msg() in class A, otherwise the display() method in class D does not know if this method exist or not in the object that you're passing to it. (What if someone makes a class E that extends A but does not have a msg() method, and you pass an E to D.display()?).
If you don't want to implement the msg() method in class A, then you can make it abstract (and you'll also have to make the class abstract).
abstract class A {
public abstract void msg();
// ...
}
more like an architecture style, I would use an interface for that, so your generic method constrains to <T extends If> void display(T ob) where If is the interface with the abstract method msg
interface If {
void msg();
}
class A {
void show() {
System.out.println("Hello A");
}
}
class B extends A implements If {
#Override
public void msg() {
System.out.println("Hello B");
}
}
class C extends A implements If {
#Override
public void msg() {
System.out.println("Hello C");
}
}
class D {
<T extends If> void display(T ob) {
ob.msg(); // here i want to do some tricks
}
}
You don't need generics for this, there is basic concept called dynamic binding in Java.
abstract class A{
void show(){
System.out.println("Hello A");
}
abstract void msg();
}
class B extends A{
#Override
void msg(){
System.out.println("Hello B");
}
}
class C extends A{
#Override
void msg(){
System.out.println("Hello C");
}
}
class D{
void display(A ob){
ob.msg();
}
}
Here an appropriate instance provided to method will determine which class method should in called at runtime.
Having some issues with genericity.
So, here is a simple version of what I'm dealing with:
I have one abstract class and two subclasses:
public abstract class A {}
public class B extends A {}
public class C extends A {}
I'm writing writers for those classes, and I want to keep the same architecture, because all those have a lot in common. But I want to be able to call the writer without instantiating it
public abstract class AWriter<T extends A> {
public void AWritingMethod(T arg) {}
}
public class BWriter extends AWriter<B> {
public static void BWritingMethod(B arg) {
AWritingMethod(arg)
}
}
public class CWriter extends AWriter<C> {
public static void CWritingMethod(C arg) {
AWritingMethod(arg)
}
}
Obviously, I can't call AWritingMethod in BWriter and CWriter, but how could I do something like that to keep most of the work in AWriter, while still keeping BWritingMethod and CWritingMethod static ?
Thanks already !
LD
You can change your code as following, add static to AWritingMethod:
public abstract class AWriter<T extends A> {
public static void AWritingMethod(T arg) {}
}
public class BWriter extends AWriter<B> {
public static void BWritingMethod(B arg) {
AWriter.AWritingMethod(arg)
}
}
public class CWriter extends AWriter<C> {
public static void CWritingMethod(C arg) {
AWriter.AWritingMethod(arg)
}
}
or you can try using new instance of BWriter and CWriter class like this:
public abstract class AWriter<T extends A> {
public void AWritingMethod(T arg) {}
}
public class BWriter extends AWriter<B> {
public static void BWritingMethod(B arg) {
new BWriter().AWritingMethod(arg);
}
}
public class CWriter extends AWriter<C> {
public static void CWritingMethod(C arg) {
new CWriter().AWritingMethod(arg);
}
}
If you want to abstract the logic out into a separate class/method, your best bet would be to do something like this:
class AWriter {
private AWriter() {}
static <T extends A> void AWritingMethod(T arg) {}
}
public class BWriter {
private BWriter() {}
public static <T extends B> void BWritingMethod(T arg) {
AWriter.AWritingMethod(arg)
}
}
public class CWriter {
private CWriter() {}
public static <T extends C> void CWritingMethod(T arg) {
AWriter.AWritingMethod(arg)
}
}
Note that AWriter is not public, which is fine if BWriter and CWriter are in the same package, plus private constructors to prevent instantiation of static-only classes. This requires a bit more boilerplate around adding generics to each static method, but you don't have a lot of choice - you cannot use a classes generic types in a static context.
It is possible to narrow return type in overriding methods in Java.
But is it possible to force this narrowing during declaration?
For example, this may be good in the pattern, where inner class is subclassed simultaneously with outer one:
public class Try_ForceNarrow {
public interface IMember {
}
public interface Container<M extends IMember> {
M createMember();
}
public static class A implements Container<A.Member> {
#Override
public Member createMember() {
return new Member();
}
public class Member implements IMember {
}
}
public static class B extends A implements Container<B.Member> {
#Override
public Member createMember() {
return new Member();
}
public class Member extends A.Member {
}
}
public static void main(String[] args) {
}
}
This code fails compile with an error of "The interface Container cannot be implemented more than once with different arguments".
How to avoid this?
Of course, I can just write
public static class B extends A {
#Override
public Member createMember() {
return new Member();
}
public class Member extends A.Member {
}
}
But this way I can forget to override createMember() and violate the pattern.
And what about A<T> implements Container<T> ? You can restrict T further as you wanted...
It appears to me that you want each subclass C to have a createMember factory method that returns a new object that has the same type. The problem is that if C1 provides a factory method that returns C1, and then C2 extends C1, there's no way to force C2 to provide its own method--it could just inherit the one from C1.
I don't think there's a solution that will catch errors at compile time, but maybe you can do something that catches the error at run time:
abstract class MemberBase {
protected abstract MemberBase doCreateMember();
protected abstract Class<?> memberClass();
public MemberBase createMember() {
MemberBase result = doCreateMember();
if (result.getClass() != memberClass()) {
throw new RuntimeException("createMember returned the wrong class");
}
return result;
}
}
public static class A extends MemberBase {
#Override
protected Member doCreateMember() {
return new Member();
}
#Override
protected Class<?> memberClass() {
return Member.class;
}
public class Member implements IMember {
}
}
public static class B extends A {
// If you forget to define this, the doCreateMember in A will be
// inherited, but it will return the wrong class and lead to a
// run-time exception
#Override
protected Member doCreateMember() {
return new Member();
}
#Override
protected Class<?> memberClass() {
return Member.class;
}
public class Member extends A.Member {
}
}
I haven't tested this, and I'm not sure it accomplishes what you are looking for. Plus I may have gotten some syntax wrong. But maybe this, or a modification of it, might be useful.
I believe this fulfills what you are trying to do.
You can create a new abstract class that implements Container which allows you to continually extend or narrow the generics, but you need to declare each class static:
class Try_ForceNarrow {
public interface IMember {
}
public interface Container<M extends IMember> {
M createMember();
}
//The abstract class that lets you continually extend or "narrow"
public static abstract class A<E extends A.Member> implements Container<E> {
public static class Member implements IMember {
}
}
//Here is the first class that extends the Abstract Class A
public static class B extends A<B.Member> { //This class now Implements Container<B.Member>
#Override
public Member createMember() {
return new Member();
}
//Since this is the first extension we will extend A.Member
public static class Member extends A.Member {
}
}
//This is an additional class that extends A but we want to extend the functionality of B.Member also.
public static class C extends A<C.Member> { //This class now Implements Container<C.Member>
#Override
public Member createMember() {
return new Member();
}
//C.Member properly extends B.Member
//if this class is going to be extended this needs to be static
public class Member extends B.Member {
}
}
}
And of course per your requirements if you remove
#Override
public Member createMember() {
return new Member();
}
From the extending sub-classes you get a compile error.
Of course it will fail, your class A implements Container<A.Member>, but your class B extends A but also implements Container<B.Member> which is like class B extends A implements Container<A.Member> Container<B.Memeber> , and in terms of the compiler, there is no difference between Container<A.Member> and Container<B.Member> due to type erasure, after compilation, all generics information will be lost, so there is no <……> after type erasure, only their upper bounds and lower bounds exist, your type parameters are unbounded so they will erase to the same type, after erasure, your class B literally looks like this class B extends A implements Container Container which is fundamentally wrong. You can narrow the return type on overrides which is called covariant return type, this will also create a bridge method in the VM to preserve porlymorphism in Generics.
Say you have a super-class. In that super class you want to pass runtime object of itself (this) as a parameter to an overloaded method. Trick is, this overloaded method is overloaded by sub-class type. When you try to do it, you'll get a
method ... is not applicable(actual argument
... cannot be converted to ... by method invocation
conversion)
Instead you would need to implement the method separately in each subtype (just to get the correct runtime class), which is a lot of duplicate effort when the contents of the method are identical.
e.g:
public class InferTypeTest {
public static void main(String[] args) {
SubClass1 s1 = new SubClass1();
s1.sayHi();
}
public static void sayHi(SubClass1 clz) {
System.out.println("clz 1");
}
private abstract static class SuperClass{
public void sayHi() {
InferTypeTest.sayHi(this);
}
}
private static class SubClass1 extends SuperClass{
}
}
Yes, this is how double dispatch works, you have to override the accept method in each subclass like this:
private static abstract class NodeWithChildren implements DomNode {
/* snip */
public void accept(DomNodeVisitor visitor) {
for (DomNode child : children) {
child.accept(visitor);
}
}
}
private static class BodyNode extends NodeWithChildren {
public void accept(DomNodeVisitor visitor) {
visitor.visit(this);
super.accept(visitor);
visitor.visited(this);
}
}
private static class DivNode extends NodeWithChildren {
public void accept(DomNodeVisitor visitor) {
visitor.visit(this);
super.accept(visitor);
visitor.visited(this);
}
}
}
BodyNode is a NodeWithChildren
DivNode is a NodeWithChidren
NodeWithChildren is a DomNode
DomPrinterVisitor is a DomNodeVisitor
DomNodeVisitor's visitor can visit "BodyNode" or "DivNode, But you are passing "NodeWithChildren" to visit.
Here BodyNode is a NodeWithChildren but NodeWithChildren is not BodyNode/
Theary is if B extends A, you can say B is a A/ not A is a B.