Help with method calls

#1

Hi,

I recently started to learn rust and now I need to some help to understand how traits/structures and functions work. Here I am exploring methods/functions/structures treating to them as primitive objects in C++. I would appreciate if someone could help me get the example working and then demonstrate how a real Rust pro would do it (comparative request here is primarily for learning purposes).

Example

trait A {
    fn add(a:i32, b:i32)->i32;
    fn sub(a:i32, b:i32)->i32;
}
trait B {
    fn get_a()-> i32; // PROBLEM
    fn get_sum()-> i32; //PROBLEM
}

struct ObjAddSub {
    oa: i32,
    ob: i32,
    sum: i32,
    sub: i32
}

impl A for ObjAddSub{
    fn add( a: i32, b: i32)-> i32{
        a+b
    }
    fn sub(a: i32, b: i32)-> i32{
        a-b
    }
}

 impl B for ObjAddSub{
    fn get_a()-> i32{
       self.a;               // PROBLEM
    }
    fn get_sum()-> i32{
       self.sum;               // PROBLEM
    }
}

impl  ObjAddSub{
    fn make(a: i32, b: i32)-> ObjAddSub{
        let t : (i32, i32) = (a,b);
        ObjAddSub{
            oa: a,
            ob: b,
            sum: add(,a,b),                // PROBLEM
            sub: match t {
                (x,y) if x > y => {sub(x,y)}    // PROBLEM
                (x,y) if y > x =>{sub(y,x)}   // PROBLEM
                _ => {0}
            }
        }
    }

}

fn main (){

    let x: i32 = 4;
    let y: i32 = 6;
    let obj = ObjAddSub::make(x,y);

    println!("a: {}, sum: {}", obj.get:a(), obj.get_sum());

}

So what I would like to have are two different traits that I can implement separately on the same structure and call functions inside of them during construction plus additional getters to get the information from the structure.

Thank you for any help you are in position to provide.

mxs

1 Like
#2

This is the version of your code that compiles: playground. But there is no real benefit in using traits here, as you refer to the concrete implementations anyway. Traits will be more beneficial if you try to write a generic function (like a function that will take any type that implements your traits).

Note that standard library provides Add and Sub traits representing these basic operations, so there is no need to create a new trait for that.

1 Like
#3

To add to @Riateche’s post, also take into account the difference between ObjAddSub::add (say inside the make fn) and <Self as A>::add (or <ObjAddSub as A>::add). The latter always calls into ObjAddSub's Add impl, whereas the former can call into an inherent method if you were to provide one (e.g. if you add an fn add(...) to the impl ObjAddSub block, that will be called instead of the impl A version).

1 Like
#4

Let me see if I got this right … if I put my add() function into impl ObjAddSub then i override any outside function calls that have the same name ? Why is that ?

#5

Thank you !! I get it now. I am aware of std functions this was just a startup example… the thing that puzzles me now is that I can easily call ObjAddSub::add(x,y) from my main() but if I need for that to be private and unreachable to anything but a set of impl "objects" that inherited my trait how would I achieve that ?

#6

You override same signature functions that are part of any impl trait blocks for ObjAddSub - the resolution is covered in more detail in the reference.

2 Likes
#7

Can you expand on this a bit more, maybe with an example?

1 Like
#8

Sure and thank you, I know i am asking silly questions at this point but I am still learning…

Example

if you remove the last line it will compile but my perception is that the last line should be a more safer way to go plus i do not understand why exactly it does not work.

#9

I think you might be asking about the difference between associated functions and methods. Have you read this section of the book?

But in short, associated functions (which is what your current add() is) are like static member functions in C++ - they don’t take a receiver. If you want to define a method, whether in a trait or an impl, you need to indicate that explicitly by adding a self, &self, or &mut self as the first argument of the signature - the link above goes over this.

2 Likes