【问题标题】:How to use generics in Java when dealing with multiples heterogeneous objects?处理多个异构对象时如何在Java中使用泛型?
【发布时间】:2021-12-31 17:09:46
【问题描述】:

假设,我有两个如下所示的类:

public class classA {
    private Boolean is_started;

    public classA(Boolean is_started) {
        this.is_started = started;
    }
    public Boolean getIs_started(){
        return this.is_started;
    }
}

public class classB {
    private String token;

    public classA(String token) {
        this.token = token;
    }
    public String get_token(){
        return this.token;
    }
}

我从另一个类中调用这两个类,如下所示:

public class CallingClass {

    public void function1() {
        ClassA stepA = new ClassA(<some boolean>);
        commonFunction(stepA);
}
    public void function2() {
        ClassB stepB = new ClassB(<some string>);
        commonFunction(stepB);
}
    public <T> void commonFunction(Class<T> dataObject) {
        //An if statement that has a condition that only calls a function in classB {
            String token = dataObject.get_token();
        }
        //An if statement that has a condition that only calls a function in classA {
        Boolean is_started = dataObject.getIS_started();
        }
//It returns error : The method [get_token()/getIS_started()] is undefined for the type Class<T>

我想确保我可以调用不同的对象而无需在函数中指定它们。例如,我想提供ClassAClassB 作为commonFunction 的参数,如上例所示。如何使用泛型实现它?

【问题讨论】:

  • 试图更好地理解你的问题,所以在你的通用函数 commonFunction 中,你想调用一个在 classA 和 classB 中的方法 get_token 并返回结果是什么?
  • 您的“classA”没有方法get_tokenClass&lt;T&gt; 指的是java.lang.Class。你调用你的类classA,在一个 sn-p 中使用小写字母,在下一个使用大写字母 ClassA。 A 类或 B 类都没有扩展/实现Class&lt;T&gt;。不太清楚您的要求或尝试实现的目标。
  • 您需要某种方式将两个类联系在一起,例如interface(因为Class 没有定义getToken 方法)
  • 我添加了一些声明以进行澄清。 @scigs

标签: java class object generics


【解决方案1】:

您需要某种方法将类联系在一起,即“此实例实现了一个名为 getToken 的方法,该方法返回某种结果”

最简单的起点是interface,例如...

public interface Tokenable<T> {
    public T getToken();
}

那么ClassAClassB 都需要根据需要实现这个interface,例如...

public class ClassA implements Tokenable<Boolean> {

    private Boolean started;

    public ClassA(Boolean started) {
        this.started = started;
    }

    @Override
    public Boolean getToken() {
        return started;
    }

}

public class ClassB implements Tokenable<String> {

    private String token;

    public ClassB(String token) {
        this.token = token;
    }

    @Override
    public String getToken() {
        return token;
    }

}

然后您就可以将回电社区化...

public class CallingClass {

    public void function1() {
        ClassA stepA = new ClassA(false);
        commonFunction(stepA);
    }

    public void function2() {
        ClassB stepB = new ClassB("hello");
        commonFunction(stepB);
    }

    public <T> void commonFunction(Tokenable<T> dataObject) {
        T token = dataObject.getToken();
    }

}

如果不提供某种共同祖先,您将无法真正使其工作 - Class 没有定义 getToken 方法,因此您需要某种共同祖先才能称之为(有一种“hacky”的方式来做,但你真的,真的,真的不想掉进那个兔子洞)

【讨论】:

  • 如果我们在commonFunction 中调用不同类的不同方法,它会起作用吗?比如说,我在不同时间调用 get_token() 和 getIs_started() ,就像我在上面的问题中编辑的那样。
  • @JJ123 同样,您需要定义某种程度的通用性 - 您不能在未定义功能的类上调用方法(通过继承或实现) - 这都是多态性
【解决方案2】:

你的字面问题的直接答案是classAclassB的唯一超类型是Object,所以你的参数类型必须是Object,你可以使用instanceof来测试它是否是特定类型的实例,如果是,则强制转换为该类型以执行只能使用该类型完成的操作:

public void commonFunction(Object dataObject) {
    if (dataObject instanceof classB) {
        String token = ((classB)dataObject).get_token();
    }
    if (dataObject instanceof classA) {
        Boolean is_started = ((classA)dataObject).getIS_started();
    }
}

但是,像这样使用instanceof 是糟糕设计的证据。如果两种不同类型的逻辑是分开的,那为什么要把它们放在同一个函数中呢?如果“token”和“is_started”应该代表相同类型的信息,那么将它们重构为接口中提供的相同方法,就像其他建议的答案一样,更有意义。

【讨论】:

    【解决方案3】:

    可能是我对您的问题遗漏了一些东西,因为尚不完全清楚您要实现的目标,但您尝试执行此操作的方式似乎不太正确。

    commonFunction 中有逻辑,如果参数是一种类型,则以一种方式运行,如果参数是另一种类型,则以另一种方式运行。看来您真正应该做的是在 ClassA 和 ClassB 中拥有该逻辑。所以他们都应该实现一些在 ClassA 内部以一种方式运行而在 ClassB 内部以另一种方式运行的方法。那么commonFunction 可以对所有参数一视同仁。

    一般来说,如果您正在测试参数的类型并在不同情况下触发不同的行为,那么这很好地表明该行为确实属于这些类本身,前提是您是定义您所在的类的人这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-19
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2018-09-29
      相关资源
      最近更新 更多