【问题标题】:Incompatible types while returning Either返回时不兼容的类型
【发布时间】:2019-08-04 12:46:29
【问题描述】:

我正在使用 vavr 的 Either 来控制我的应用程序的流程,它运行良好,直到我不必混合几个域...

首先,我有一个在域之间共享的接口。

public interface DomainError {
    String getCause();
}

同样的成功,当我只是想通知用户并且不需要返回特定对象时。

@RequiredArgsConstructor
@Getter
public class SuccessMessage {
    private final String message;
}

现在,每个域都像这样实现DomainError

public enum UserError implements DomainError {
    USERNAME_ALREADY_EXISTS("Username already exists"),
    INVALID_EMAIL("Provided email address is invalid");

    private final String cause;
    UserError(String cause) {
        this.cause = cause;
    }
    @Override
    public String getCause() {
        return cause;
    }
}

类似地,它会查找 EmailError,其中只有另一个值。现在,我有EmailFacade

public class EmailFacade {
    private final SendEmailUseCase sendEmail;
    private final CreateEmailUseCase createEmail;

    public Either<DomainError, SuccessMessage> sendUserVerificationEmail(UUID uuid, String receiver) {
        return sendEmail.send(createEmail.createUserVerificationEmail(uuid, receiver));
    }
}

其中一项服务返回

class SendEmailUseCase {
    Either<DomainError, SuccessMessage> send(EmailMessage message) {
        if(message == null) return Either.left(EmailError.EMPTY_MESSAGE);
        log.info(message.toString());
        return Either.right(new SuccessMessage("Email sent"));
    }
}

现在,我需要从处理用户注册的其他域调用它。

为了做到这一点,我写了这个方法

Either<DomainError, SuccessMessage> register(RegisterUserDto registerUserDto) {
        if(userRepository.findUser(registerUserDto.getUsername()).isPresent())
            return Either.left(UserError.USERNAME_ALREADY_EXISTS);
        Either<DomainError, User> userCreationResult = User.createUser(registerUserDto);
        return userCreationResult
            .map(user -> {
                userRepository.save(user.toDto());
                final UUID uuid = verificationTokenRepository.generateVerificationToken(user.getUsername());
                return emailFacade.sendUserVerificationEmail(uuid, user.getUsername());
            });
    }

我在这里做的事情很少,但相关部分是最后一个 return 语句,以上所有内容都在工作。 emailFacade.sendUserVerificationEmail() 返回Either&lt;DomainError, SuccessMessage&gt;,与register() 方法相同。但是由于某种原因,我收到了这个错误

错误:(28, 17) java: 不兼容的类型: 推断变量 U 有 不相容的界限 等式约束:com.johndoe.myapp.domain.SuccessMessage 下界:io.vavr.control.Either&lt;com.johndoe.myapp.domain.DomainError,com.johndoe.myapp.domain.SuccessMessage&gt;

我真的无法理解这里出了什么问题......

【问题讨论】:

标签: java either vavr


【解决方案1】:

方法map 用于转换容器内的值。在您的情况下,它为您提供 User 的值并期望您返回转换后的值。因此,如果您返回 Either&lt;DomainError, User&gt;,则结果类型将为 Either&lt;DomainError, Either&lt;DomainError, User&gt;&gt;,这不是方法签名所期望的返回类型。

如果你不想从函数返回 Either,那么你应该使用 flatMap 代替,这会将结果扁平化为 Either&lt;DomainError, User&gt;

return userCreationResult
   .flatMap(user -> { //replace map with flatMap
        userRepository.save(user.toDto());
        final UUID uuid = verificationTokenRepository.generateVerificationToken(user.getUsername());
        return emailFacade.sendUserVerificationEmail(uuid, user.getUsername());
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 2014-08-29
    • 2016-05-28
    • 2012-08-06
    相关资源
    最近更新 更多