【问题标题】:How can I refactor a method with an unknown Class as a parameter?如何重构以未知类为参数的方法?
【发布时间】:2017-08-14 18:39:00
【问题描述】:

我想让这个方法可重用,但我不确定如何提供一个可以在以下上下文中工作的参数:

  • service.getPosts() // The method called, i.e. getPosts() should vary depending on the class parameter
  • for (Post object : postResponse.getResults()) { // I want the Post class to come from the parameter
  • List<Post> objects = postResponse.getResults(); // I want the class passed into this list to also come from that same parameter

方法调用:

retrieveData(mCardAdapter, Post.class);

方法:

private void retrieveData(final CardAdapter mCardAdapter, final Class classParam) {
        RetrofitService service = ServiceFactory.createRetrofitService(RetrofitService.class, RetrofitService.SERVICE_ENDPOINT);
        service.getPosts()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<PostResponse>() {
                    @Override
                    public final void onCompleted() {
                        setRefreshingFalse();
                        Log.e("RetrofitService", "Retrofit Request Completed!");
                    }

                    @Override
                    public final void onError(Throwable e) {
                        setRefreshingFalse();
                        Log.e("RetrofitService", e.getMessage());
                    }

                    @Override
                    public final void onNext(PostResponse postResponse) {
                        if (postResponse != null) {
                            Log.e("RetrofitService", "Returned objects: " + postResponse.getResults());

                            for (Post object : postResponse.getResults()) {
                                Log.e("RetrofitService", object.getObjectId() + ": " + object.getText());
                            }

                            /*for (Post post : postResponse.getResults()) {
                                mCardAdapter.addData(post);
                            }*/

                            setRefreshingFalse();

                            mCardAdapter.clear();
                            List<Post> objects = postResponse.getResults();
                            mCardAdapter.addData(objects);

                        } else {
                            Log.e("RetrofitService", "Object returned is null.");
                        }

                    }

                });
    }

当我通过Class classParam 时,我只是得到Unkown class: 'classParam' 作为错误。

服务:

public interface RetrofitService {

    String SERVICE_ENDPOINT = "https://parseapi.back4app.com";

@Headers({
            "X-Parse-Application-Id: asdf",
            "X-Parse-REST-API-Key: asdf"
    })
    @GET("/classes/Post")
    Observable<PostResponse> getPosts();

}

发布对象:

public class Post implements Serializable {

    private static final String CLASS_NAME = "Post";

    private String objectId;
    private String text;

    public Post() {
    }

    public String getClassName() {
        return CLASS_NAME;
    }

    public String getObjectId() {
        return objectId;
    }

    public void setObjectId(String objectId) {
        this.objectId = objectId;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

}

已更新(根据 Roman 的建议):

【问题讨论】:

  • When I pass Class classParam...的调用代码是什么?
  • 您可以使用接口还是无法控制传入的类的来源?
  • 我用 POJO 和 Rest 接口更新了我的问题,但我想我的意思是我只想能够对不同的类重用 retrieveData 方法,所以我不必重写代码。
  • 你是说你不想要泛型使用,因为它需要重写代码并且更喜欢类型值对和强制转换?
  • 非常简单的例子。在调用retrieveData(...) 之前说一下,我有一个带有列表的对话框,即developer.android.com/guide/topics/ui/dialogs.html#AddingAList。测试仪有一个可以选择的类列表。在按下其中一个类时,我们调用retrieveData(...)。如果选择是“Post”,我们称 Post 对象。如果是“评论”等...可以将retrieveData(...) 方法复制并粘贴10 次,但那有什么乐趣呢? :P

标签: java object methods delegates


【解决方案1】:

您没有显示PostResponse 代码,但我想是这样的:

public class PostResponse {
    private List<Post> results;

    public List<Post> getResults() {
        return results;
    }

    ....
}

那么你可以做这样的事情。

首先,参数化Response(用来代替PostResponse):

public class Response<T> {
    private List<T> results;

    public List<T> getResults() {
        return results;
    }

    ....
}

其次,使用类型参数更改您的主要方法签名:

private <T> void retrieveData(final CardAdapter mCardAdapter, final Class<T> classParam, DataSaver<T> saver) {
...
}

在您的retrieveData() 方法中,您使用T 而不是PostResponse&lt;T&gt; 而不是PostResponse

但你也必须处理

mCardAdapter.addData(objects);

在这里,简单的类型参数化很可能不起作用。您必须使用最后一个参数 (saver) 将结果放入您的容器:

saver.save(results);

在你的 saver 实现中你实际上做了

public void save(List<Post> posts) {
    mCardAdapter.addData(posts);
}

DataSaver 也是通用的:

public interface DataSaver<T> {
    void save(List<T> objects);
}

【讨论】:

  • T 可以绑定到所需的类型(可能是将传递给通用类型参数的所有值的父级)以避免处理 mCardAdapter.addData(objects);
  • 为什么T到处都没有解决?我需要导入一些东西吗?顺便说一句,使用 PostResponse 类。
  • 啊,RetrofitService 本身似乎不接受参数化。需要覆盖超类。
  • T 本身不是一个类,它是一个类型参数;它在尖括号中“声明”。你不需要导入它。当您在此特定调用中写入 retrieveData(mCardAdapter, Post.class, new PostDataSaver() 时,PostDataSaver implements DataSaver&lt;Post&gt;T 变为 Post
  • 当我调用retrieveData(mCardAdapter, Post.class, new PostDataSaver()); 它希望我的retrieveData 方法看起来像这样:private void retrieveData(final CardAdapter mCardAdapter, final Class&lt;Post&gt; classParam, PostDataSaver saver) { 而不是private void retrieveData(final CardAdapter mCardAdapter, final Class&lt;T&gt; classParam, DataSaver&lt;T&gt; saver) {... 当我参数化PostResponse 时,Ts 是红色的并且无法解析.
猜你喜欢
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
  • 2019-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多