A trait of traits?

So I am trying to use traits now. I did this:

trait BerekenOppervlakte {
   fn oppervlakte(&self) -> f64;
}

trait BerekenInhoud {
    fn inhoud(&self, hoogte: f64) -> f64 {
        self.oppervlakte() * hoogte
    }
}

struct Vierkant {
    zijde: f64,
}

impl BerekenOppervlakte for Vierkant {
    fn oppervlakte(&self) -> f64 {
        self.zijde * self.zijde
    }
}

impl BerekenInhoud for Vierkant {}



fn main() {
    let vierkant = Vierkant ( zijde: 2.0);
// do stuff with the vierkant
}

If I do this with only the oppervlakte-trait it works like I expected. But when I add the inhoud trait, the compiler tells me about the oppervlakte trait “perhaps you need to add a supertrait for it”.

So I can imagine more or less what is wrong with my idea, but just to be sure: where did I go wrong in my thinking?

1 Like

Please use English names in code. It's hard to tell what you are even trying to do.

If you are trying to cerate a blanket impl, then you need to implement the trait for a generic type. Traits are not types, so you can't implement a trait for a trait. You probably meant

impl<T: Vierkant> BerekenInhoud for T {}
2 Likes

You have a default implementation for the BerekenInhoud::inhoud method. Because this could be copy+pasted into any implementation, it needs to be valid for all possible implementations of the trait. Not every type is guaranteed to have an oppervlakte method, so the code is invalid.

When thinking about whether generic code is valid or not, remember that the compiler doesn't consider how the code is used/which specific types the trait is implemented for. The compiler checks validity entirely based on the interface you've specified, and any type constraints you've specified. That you've only ever implemented BerekenInhoud for the Vierkant type (which also has a BerekenOppervlakte implementation) is irrelevant.

Edit: another way to look at it: nowhere in the definition of BerekenInhoud or the inhoud method did you specify that an oppervlakte method must exist. It might, but you didn't require it.

4 Likes

my apologies. It is about a square, with a surface and contents? I wasn’t sure about the correct translation for the mathematical terms.

So, if I want to have this trait for different Structs (say, square, circle, triangle), should I make it with

 impl<T: Square, Circle, Trangle> BerekenInhoud for T {
    fn content(&self, height: f64) -> f64 {
        self.surface() * height
    }
}

or am I still thinking wrong?

No, you can't use specific concrete types as constraints. Instead, you need to specify what traits the generic type T must implement. e.g.

impl<T: Surface> BerekenInhoud for T { ... }

trait Surface { fn surface(&self) -> f64; }

impl Surface for Square { ... }
impl Surface for Circle { ... }
impl Surface for Triangle { ... }
3 Likes

I think I understand. Going to try it out! Thanks!

You seem to be fundamentally confused about the notation here. impl does not denote a method in itself. I suggest you study the syntax first to be able to ask meaningful questions.

The trait bound Type: Trait specifies the constraint that Type must implement Trait. It does not restrict to a set of concrete types. It doesn't have anything to do with methods.

1 Like

ok, thanks

Should anyone be wrestling with something similar, it may help to know I finally got it working.

trait CalculateContent: CalculateSurface {
    fn content(&self, height: f64) -> f64 {
        self.surface() * height
    }
}

proved to be the working solution.

2 Likes

Regarding the english translation: it is way better to use correct native words than wrong translations. While "content" isn't the translation of "inhoud" (it is "volume") it isn't misleading, but "surface" is the "oppervlakte" of all 6 sides of the rectangular cuboid summed. The correct translation of "oppervlakte" is "area". Please, @Abmvk do not take that as criticism of your translation, but, please @H2CO3 do not force people to actually make their code "wrong" for readers.
One way to get to the correct term (as long as it's a "simple" mathematical one, as usage of others may differ) is using Wikipedia - Oppervlakte and the button for "other language", which leads to Wikipedia -Area.

Because I saw the thread about the usage of traits: this (mathematics) is a case where you do not want to use a type class hierarchy (sorry, trait hierarchy). But this is another discussion.

13 Likes

I am not forcing anyone to be wrong. This is an English language forum. It is 100% the asker's responsibility to ask a correct question if they expect a useful answer. I do not believe that those who already offer their time and effort to answer should additionally bear the burden of translating (and potentially mistranslating) from another language.

3 Likes

Speaking as someone who only speaks English: literally nothing about this question requires understanding the names. They may as well be Foo Bar Baz.

That said, there are plenty of times when it makes sense to ask clarifying questions to be able to better help the asker, but most of the time you should also put in a good effort to answer anyway.

9 Likes

Yes, strictly speaking, it's not a requirement. It's just syntax. But chewing through a bunch of unfamiliar words is just unnecessary cognitive load, and that is a very real effect.

3 Likes

I do understand it is easier to understand the question when in English, and I honestly slapped myself for not thinking of area and volume. I very much respect and enjoy the great help this forum offers. I don’t feel insulted or forced in any way, I appreciate the comments about using English.

4 Likes