0

I am trying to convert the following classes in C# over to Java.

Result is a non-generic class that is extended by the generic Result<T> class.

Their sample usages are as follows:

// When we only care if the operation was successful or not.
Result result = Result.OK();

// When we also want to store a value inside the Result object.
Result<int> result = Result.OK<int>(123);    

In Java, each class needs to be defined in its own file (unless they're embedded).

Unfortunately, I cannot find a way to have the base and extended classes share the same name like they do in C#.

Is there a way to convert the following C# code to Java?

Result.cs:

using System;

namespace MyProject
{
    public class Result
    {
        private bool _isSuccess;
        private string _errorMsg = "";

        public bool IsSuccess()
        {
            return _isSuccess;
        }

        public bool IsFailure()
        {
            return !_isSuccess;
        }

        public string ErrorMsg()
        {
            return _errorMsg;
        }

        public Result(bool isSuccess, string errorMsg)
        {
            bool errorMsgIsEmpty = string.IsNullOrEmpty(errorMsg);

            if (isSuccess && !errorMsgIsEmpty)
            {
                throw new Exception("cannot have error message for successful result");
            }
            else if (!isSuccess && errorMsgIsEmpty)
            {
                throw new Exception("must have error message for unsuccessful result");
            }

            _isSuccess = isSuccess;

            if (!errorMsgIsEmpty)
            {
                _errorMsg = errorMsg;
            }
        }

        public static Result Fail(string errorMsg)
        {
            return new Result(false, errorMsg);
        }

        public static Result<T> Fail<T>(string errorMsg)
        {
            return new Result<T>(default(T), false, errorMsg);
        }

        public static Result OK()
        {
            return new Result(true, "");
        }

        public static Result<T> OK<T>(T value)
        {
            return new Result<T>(value, true, "");
        }
    }

    public class Result<T> : Result
    {
        private T _value;

        public T Value()
        {
            return _value;
        }

        public Result(T value, bool isSuccess, string errorMsg) : base(isSuccess, errorMsg)
        {
            _value = value;
        }
    }
}

UPDATE: Special thanks to @Juan Cristóbal Olivares below for the answer! Below are my changes:

NOTE: I had to rename the typed fail and ok functions to failT and okT respectively because Java does not allow functions that only differ by the return type.

Result.java:

public class Result<T> {
    private boolean isSuccess;
    private String errorMsg = "";
    private T value;

    public boolean isSuccess() {
        return isSuccess;
    }

    public boolean isFailure() {
        return !isSuccess;
    }

    public String errorMsg() {
        return errorMsg;
    }

    public T value() {
        return value;
    }

    public Result(boolean isSuccess, String errorMsg) throws Exception {
        boolean errorMsgIsEmpty = StringUtil.IsNullOrEmpty(errorMsg);

        if (isSuccess && !errorMsgIsEmpty) {
            throw new Exception("cannot have error message for successful result");
        } else if (!isSuccess && errorMsgIsEmpty) {
            throw new Exception("must have error message for unsuccessful result");
        }

        this.isSuccess = isSuccess;

        if (!errorMsgIsEmpty) {
            this.errorMsg = errorMsg;
        }
    }

    public Result(T value, boolean isSuccess, String errorMsg) throws Exception {
        this(isSuccess, errorMsg);
        this.value = value;
    }

    public static Result<?> fail(String errorMsg) throws Exception {
        return new Result<>(false, errorMsg);
    }

    public static <T> Result<T> failT(String errorMsg) throws Exception {
        return new Result<T>(null, false, errorMsg);
    }

    public static Result<?> ok() throws Exception {
        return new Result<>(true, "");
    }

    public static <T> Result<T> okT(T value) throws Exception {
        return new Result<T>(value, true, "");
    }
}

Sample usages:

// When we only care if the operation was successful or not.
Result<?> result = Result.ok();

// When we also want to store a value inside the Result object.    
Result<Integer> result = Result.okT(123);    
2
  • You could have them in separate packages Commented Jan 15, 2020 at 4:17
  • I feel like one of OptionalInt, Optional, and CompletableFuture will fulfill this need. Commented Jan 15, 2020 at 5:19

1 Answer 1

1

When you create a C# generic class with 1 generic argument, this class is generated:

SomeClass`1

See What's the meaning of “apostrophe + number” in the object type of properties with generics (eg. “Collection`1”)?.

So while the non generic class is named SomeClass, the generic versions are SomeClass`1, SomeClass`2, etc (depending on the number of generic arguments).

Java generics are different. Generic information is removed at compile time.

See Are generics removed by the compiler at compile time.

This means that the non generic and generic versions are just the same class (SomeClass).

So, for this usecase, you just may need to define the generic version. This version will work for generic and non generic cases.

Sign up to request clarification or add additional context in comments.

2 Comments

I see... I'll try creating just the generic class in Java then and see how it goes. Thanks!
It worked! I added my Java conversion to my original question above. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.