How a function can return two types?

#1

Hey, I’m trying to return two different types in one function, in OOP normally i utilize polymorphism.
Example, a have a simple interface or an abstract class and an instance that implements that interface, so, I can have two types that implements that interface.

Pseudo Code

public interface base {
    public void something();
}

public class One implements base {
    public void something() {}
}

public class Two implements base {
    public void something() {}
}

public class Operation {
    public base test() {
        if (true) {
            return new One();
        } else {
            return new Two();
        }
    }
}

class Playground {
    public static void main(String[ ] args) {
        
        base base_one = new One();
        base base_two = new Two();
        
        Operation test = new Operation();
        
        base obj = test.test();
        
        obj.something();
        
    }
}

In Rust, the closest I got is trait object, but… I can’t use a trait that contain a Self. The error is on function instance()

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=2ee6afd631234b0c3c0ad0ab1eb7909f

I know that the rust way is composition over inheritance, but how do you translate an old code base in OOP to Rust?, I have some projects that would like to make in Rust, but sometimes a I get stuck, is not simple to redefine an architecture. Anyway if you know a material that explain how to make x in y lang to rust. Sorry for the bad English.

#2

You have to add where Self: Sized to trait methods that do not take self.

1 Like
#3

It might be more helpful if you explain an actual scenario in which you’ve wanted to do something like this - in my experience, trying to translate OOP concepts directly into Rust makes things harder than they need to be.

4 Likes
#4

thanks, now works but I can’t use the TSociable::instance() right?

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=a5cb7ff741c6b3abce7a504b17f6dce8

#5

I don’t have a concrete example now, but sometimes I need work with struct that I will know only in runtime, in this example I tried express this “problem”.

#6

Consider returning an enum. For one-off cases there’s the either crate.

3 Likes
#7

Trait objects are a valid solution to that (as is wrapping the types in an enum, as @kornel suggested) - you’re only running into issues here because you’re effectively trying to have a trait construct itself. That doesn’t really work very well - you have to add the Sized bound as @mmstick suggested, but even then you can’t use the TSociable::instance() way of calling the function. There’s a good Stack Overflow thread on why this is the case here: https://stackoverflow.com/questions/38159771/why-can-a-trait-not-construct-itself

The closest approximations to your original attempt that would work would be to either:

Which one would work best depends on the situation :slight_smile:

2 Likes
#8

Thanks, the solution is more simple that I expect , I was really complicating the things.

1 Like