该方法返回带有子类字段的超类对象

时间:2018-03-31 15:34:45

标签: java spring

我在程序中有一个Movie对象

public class Movie extends BaseDTO {
      ...
      public static class Builder<T extends Builder> extends BaseDTO.Builder<T> { ... }
}
来自此对象的

继承UserMovie

public class UserMovie extends Movie {
     //there are two additional fields
     private final Integer yourRating;
     private final boolean favorited;

     public static class Builder extends Movie.Builder<Builder> { ... }
}

在代码的某些部分,我想将实体转换为DTO对象。我有两种方法。一个将实体转换为Movie DTO

static Movie toMovieDto(final MovieEntity movieEntity) {
    return ((Movie.Builder) initMovieDto(movieEntity)).build();
}

转换为UserMovie DTO的第二种方法

static UserMovie toUserMovieDto(final MovieEntity movieEntity, final UserEntity userEntity) {
    final UserMovie.Builder builder = initMovieDto(movieEntity);

   builder.withYourRating(...);
   builder.withFavorited(userEntity.getFavoritesMovies().contains(movieEntity));

    return builder.build();
}

这两种方法都使用常用方法在Builder模式中初始化数据

private static UserMovie.Builder initMovieDto(final MovieEntity movieEntity) {
    final UserMovie.Builder builder = new UserMovie.Builder(
            movieEntity.getTitle(),
            movieEntity.getType()
    )
            .withId(movieEntity.getId().toString());

    builder.withRating(...);
    ...
    return builder;
}

事实证明toMovieDto方法返回UserMovie对象。为什么会这样?我不希望在UserMovie中返回Movie的私人字段。如何解决?

1 个答案:

答案 0 :(得分:0)

您是否担心有人可能会将从Movie返回的toMovieDto投放到UserMovie?我不会那么担心 - 这需要明确的铸造。 (比较如何定义例如Collections类中的方法,或者在任何Collection实现中的方法。

如果您真的担心安全性(并且仅在这种情况下),则需要创建另一个initMovieDto方法,即来自Movie的用户构建器,而不是当前的UserMovie

这样的事情:

private static Movie.Builder initMovieDto(final MovieEntity movieEntity) {
    final Movie.Builder builder = new Movie.Builder(
            movieEntity.getTitle(),
            movieEntity.getType()
    )
            .withId(movieEntity.getId().toString());
    ...
    return builder;
}

static Movie toMovieDto(final MovieEntity movieEntity) {
    return ((Movie.Builder) initMovieDto(movieEntity)).build();
}

并为UserMovie分开:

private static UserMovie.Builder initUserMovieDto(final MovieEntity movieEntity) {
    final UserMovie.Builder builder = new UserMovie.Builder(
            movieEntity.getTitle(),
            movieEntity.getType()
    )
            .withId(movieEntity.getId().toString());

    builder.withRating(...);
    ...
    return builder;
}

static UserMovie toUserMovieDto(final MovieEntity movieEntity, final UserEntity userEntity) {
    final UserMovie.Builder builder = initUserMovieDto(movieEntity);

   builder.withYourRating(...);
   builder.withFavorited(userEntity.getFavoritesMovies().contains(movieEntity));

    return builder.build();
}

这样,您不仅会返回您想要的界面,还会返回与toMovieDtotoUserMovieDto中的返回类型相同类型的具体类。

另一种选择是定义UserMovie构建器,使其中一个选项可以接受“影片”构建器。