简体   繁体   中英

Handling multiple Classes with Types in client code

Suppose if I have the following classes

class A {} 
class B {} 

abstract class ParentClass<T> {
    abstract void accept(T t);
} 

class Child1 extends ParentClass<A> {
    void accept(A a) {} 
} 

class Child2 extends ParentClass<B> {
    void accept(B b) {} 
} 

Now if I have a client code where I want to have both instances of child1 and child2 mapped to a string in a map (and) also make use of accept method, seems its impossible and I get it why. Is there a Better work around?

My client code looks like,

class Client {
    Map<String, ParentClass<?>> map = new HashMap<>();

    public Client() {
       map.put("C1", new Child1());
       map.put("C2", new Child2());
    } 

    void callAccept(String type, Object o) {
        map.get(type).accept(o); //error
    } 

} 

#Update 1 Adding the return type in the example as I missed when I typed the question from mobile.

"Better" depends on what you want to achieve. As I understand your question, you just want to be able to compile the code and understand it. Many variations are possible, and "best" would depend on the business problem you are addressing.

Absent a business problem that the code might address, here is code that compiles without error. I fixed several errors in your code:

// ParentClass.java

class Base {}
class A extends Base {}
class B extends Base {}

abstract class ParentClass<T> {
   abstract ParentClass<?> accept(Base base);
}

class Child1 extends ParentClass<A> {
  /* No idea what this is supposed to do, 
     so just return something type-compatible */
  ParentClass<A> accept(Base base) { return this; }
}

class Child2 extends ParentClass<B> {
  /* No idea what this is supposed to do, 
     so just return something type-compatible */  
  ParentClass<B> accept(Base base) { return this; }
}

ParentClass , a container, is subclassed as Child1 and Child2 .

Base above is a base class for the payload contained within ParentClass subclasses. You need a base class for the payload because the container class ( ParentClass ) is subclassed, and you want to be able to mix and match payloads.

// Client.java

import java.util.HashMap;
import java.util.Map;

class Client {
  Map<String, ParentClass<?>> map = new HashMap<>();

  public Client() {
     map.put("C1", new Child1());
     map.put("C2", new Child2());
  }

  void callAccept(String type, Base base) {
      map.get(type).accept(base);
  }
}

Java, Scala, Haskell and other languages use type theory , specifically category theory to define precisely what is allowable. Practically speaking, and without getting lost in math, the general guidelines above are a few of the considerations for working with generics.

For more information, please read the section on generic containers in “Effective Java” by Joshua Bloch. I don't believe he mentions category theory, which is good.

If you are interested in "just enough" type theory, read about covariant types .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM