简体   繁体   English

处理多个异构对象时如何在Java中使用generics?

[英]How to use generics in Java when dealing with multiples heterogeneous objects?

Let's say, I have two classes that look like this:比方说,我有两个看起来像这样的类:

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;
    }
}

I am calling those two classes from another class like this:我从另一个 class 调用这两个类,如下所示:

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>

I want to make sure that I can call different objects without specifying them in the function.我想确保我可以调用不同的对象,而无需在 function 中指定它们。 For example, I want to supply ClassA and ClassB as an argument to the commonFunction as in the example above.例如,我想提供ClassAClassB作为commonFunction的参数,如上例所示。 How do I make it happen with generics?如何使用 generics 实现它?

You need some way to tie the classes together which says "this instance implements a method called getToken which returns some kind of result"您需要某种方法将类联系在一起,上面写着“此实例实现了一个名为getToken的方法,该方法返回某种结果”

The simplest place to start would be a interface , for example...最简单的起点是interface ,例如...

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

Then both ClassA and ClassB would need to implement this interface as required, for example...那么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;
    }

}

And then you can communalise the call back...然后你可以将回电公用化......

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();
    }

}

Without providing some kind of common ancestor, you're not really going to be able to get it to work - Class doesn't define a getToken method, so you need some kind of common ancestor in order to call it (there is a "hacky" way to do it, but you really, really, really don't want to go down that rabbit hole)如果不提供某种共同祖先,您将无法真正使其工作 - Class没有定义getToken方法,因此您需要某种共同祖先才能调用它(有一个“ hacky”的方法,但你真的,真的,真的不想 go 掉进那个兔子洞)

It could be that there's something I'm missing about your question because it's not entirely clear what you are trying to achieve but something doesn't seem quite right about the way you're trying to do this.可能是我对您的问题有所遗漏,因为尚不完全清楚您要达到的目标,但是您尝试执行此操作的方式似乎不太正确。

You have logic in commonFunction that behaves one way if the argument is one type and another way if the argument is the other type.如果参数是一种类型,则commonFunction中的逻辑以一种方式运行,如果参数是另一种类型,则以另一种方式运行。 It seems like what you really should do is have that logic inside ClassA and ClassB.看来您真正应该做的是在 ClassA 和 ClassB 中拥有该逻辑。 So they should both implement some method that behaves one way inside ClassA and the other way inside ClassB.所以他们都应该实现一些方法,在 ClassA 内部以一种方式在 ClassB 内部以另一种方式运行。 Then commonFunction can treat all arguments the same.那么commonFunction就可以对所有的arguments一视同仁了。

In general, if you are testing the type of an argument and triggering different behaviour in different cases then it's a pretty good indication that the behaviour really belongs inside those classes themselves, provided you are the one defining the classes which you are in this case.一般来说,如果您正在测试参数的类型并在不同的情况下触发不同的行为,那么这很好地表明该行为确实属于这些类本身,前提是您是在这种情况下定义您所在的类的人。

The direct answer to your literal question would be that the only supertype of classA and classB is Object , so your parameter type must be Object , and you can use instanceof to test if it's an instance of a particular type, and if so, cast to that type to do stuff that can only be done with that type:您的字面问题的直接答案是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();
    }
}

However, using instanceof like this is evidence of bad design.然而,像这样使用instanceof是糟糕设计的证据。 If the logic for the two different types is separate, then why put them in the same function?如果两种不同类型的逻辑是分开的,那为什么要把它们放在同一个 function 中呢? If the "token" and "is_started" are supposed to represent the same kind of information, then refactoring them to the same method provided in an interface, like other answers suggested, makes more sense.如果“token”和“is_started”应该代表相同类型的信息,那么将它们重构为接口中提供的相同方法,就像建议的其他答案一样,更有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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