[rust-dev] Inheritance / delegation

Ben Foppa benjamin.foppa at gmail.com
Fri Oct 17 12:01:10 PDT 2014


Your struct has a fixed size - a reference is a pointer. Which is why it
requires a lifetime - how long is the pointed-to data alive for? And so you
need to tell it - in your enum example, you need to say Bag<'a> (for some
defined 'a). For example, Bag<'static> means the pointed-to data lives as
long as the program.

On Fri, Oct 17, 2014 at 11:50 AM, David Henningsson <diwic at ubuntu.com>
wrote:

>  Thanks for the answer. Deref is a new one for me, looks interesting by
> means of abstraction.
>
> I'm also coming from the C camp but I'm not sure how to write the code
> that I want in rust. Yet. :-)
>
> E g, here's one, somewhat related, C example that I'm not sure how to do
> in Rust:
>
> struct bag {
>    int price;
>    int nitems;
>    int []items;
> };
>
> struct cart { /* ... */ };
>
> struct shopping {
>    int kind; /* 0 means bag, 1 means cart */
>    union {
>       struct bag bag;
>       struct cart cart;
>    }
> }
>
> struct shopping* make_shopping_bag(int price, int nitems, int *items)
> {
>     struct shopping* result = malloc(sizeof(shopping)+nitems*sizeof(int));
>     result.kind = 0;
>     result.bag.price = price;
>     result.bag.nitems = nitems;
>     memcpy(result.bag.items, nitems*sizeof(int));
> }
>
>
> So, the bag struct would probably look like this in Rust:
>
> struct Bag <'a> {
>   price: int,
>   weights: & 'a [int],
> }
>
>  1) It feels like "weights: [int]" would be more like the way I want it,
> and the declaration compiles, but i can't initialize the struct or have it
> as a local variable because its size is now unkown. Even though a static
> initialization like "let b = Bag { price: 10, weights: [3,5,7] }" would be
> trivial to calculate the total size of, the compiler seems not to be able
> to do this.
>
>  2) I'm not sure why this lifetime has to be explicit, should default to
> "same lifetime as parent struct" IMO.
>
>  3) And when I try to do like:
>
> enum Shopping {
>   InBag(Bag),
>   InCart( /* ... */ ),
> }
>
> I get an error: "error: wrong number of lifetime parameters: expected 1,
> found 0". I've tried both "InBag('a Bag)" and "InBag(Bag + 'a)" but that
> ends up with other errors instead...so no idea on what to do about that?
>
>
> On 2014-10-17 18:37, Clark Gaebel wrote:
>
>  Rust is not a replacement for java, it’s a replacement for C and C++.
>
>  To solve little “puzzles” like this, i tend to ask myself “how would I
> do this in C”, and then write that code in rust. Building inheritance trees
> is generally the wrong way of approaching problems. In cases where it does
> apply, you can still do it, but be gentle. Try not to lean on them as your
> primary means of abstraction.
>
>  Anyhow, on to your actual problem.
>
>  Something which might be worth trying is implementing `Deref<Circle>`
> and `DerefMut<Circle>` for your pancake, then having a
> `DList<Box<Deref<Circle>>>` (or just use a normal &, if you want that).
>
>  Then you can call all your circle traits after a quick call to
> `.deref()`, AND your `DList` will free everything properly.
>
>  But again, there’s probably a simpler solution that doesn’t involve
> “inheritance” that you should consider. Maybe a DList of enums? Maybe just
> a Vec<uint> in this case? Think about how you’d do it in C.
>
>  Regards,
>   - Clark
>
>
>
>  On Fri, Oct 17, 2014 at 4:27 AM, David Henningsson <diwic at ubuntu.com>
> wrote:
>
>> Hmm, right. The as_* could probably useful to write a macro for.
>>
>> Coming from the C/Java side of things I have to figure out how this
>> works in a bigger context, e g a DList or other structure owning objects
>> implementing HasArea. This seems to compile, e g:
>>
>> impl Pancake {
>> fn as_box_circle(&self) -> Box<Circle> { box self.circle }
>> }
>>
>> fn make_pancake(dl: &mut DList<Box<HasArea>>) {
>> let p = Pancake { circle: Circle { x: 0f64, y: 0f64, radius: 1f64
>> }, is_tasty: true };
>> dl.push(p.as_box_circle());
>> }
>>
>> But I'd assume that make_pancake would now make a copy of the pancake's
>> circle, rather than taking ownership of the entire pancake, right? The
>> pancake then gets dropped at function return.
>>
>> In this simple example perhaps this does not make that much of a
>> difference though, but if you imagine a C struct like:
>>
>> struct list {
>> list *next;
>> circle *data;
>> }
>>
>> You can now put a pointer to a pancake as data, use it as a circle, and
>> when you finally free the list and the data that goes with it, the
>> entire pancake will be freed. This you cannot do in rust...or can you?
>>
>>
>> On 2014-10-17 07:59, Clark Gaebel wrote:
>> > impl Pancake {
>> > fn as_circle(&self) -> &Circle { &self.circle }
>> > fn as_mut_circle(&mut self) -> &mut Circle { &mut self.circle }
>> > }
>> >
>> > The compiler will optimize trivial functions, except cross-crate. In
>> > those cases, use an #[inline] annotation.
>> >
>> >
>> >
>> > On Thu, Oct 16, 2014 at 10:57 PM, David Henningsson <diwic at ubuntu.com
>> > <mailto:diwic at ubuntu.com> <diwic at ubuntu.com>> wrote:
>> >
>> > This is probably a previously asked question, but I couldn't find
>> > it on
>> > Google, so...
>> >
>> > Let's extend the Circle example from the guide a little:
>> >
>> > struct Circle {
>> > x:f64,
>> > y:f64,
>> > radius:f64,
>> > }
>> >
>> > trait HasArea {
>> > fn area(&self)-> f64;
>> > }
>> >
>> > impl HasArea for Circle {
>> > fn area(&self)-> f64 {
>> > std::f64::consts::PI * (self.radius * self.radius)
>> > }
>> > }
>> >
>> > struct Pancake {
>> > circle: Circle,
>> > is_tasty: bool,
>> > }
>> >
>> >
>> > ...now, what is the easiest way I can implement HasArea for
>> > Pancake? I
>> > could do this:
>> >
>> > impl HasArea for Pancake {
>> > fn area(&self) -> f64 { self.circle.area() }
>> > }
>> >
>> > ...but that means a lot of boiler-plate code, especially if
>> > HasArea has
>> > many methods. Hopefully rust will just inline/optimise the
>> > redirection
>> > away in most cases to avoid the runtime cost, but is there a
>> > smarter or
>> > more idiomatic way of doing this?
>> >
>> > // David
>> >
>> > _______________________________________________
>> > Rust-dev mailing list
>> > Rust-dev at mozilla.org
>> > https://mail.mozilla.org/listinfo/rust-dev
>> >
>> >
>>
>>
>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20141017/c6ff0d08/attachment.html>


More information about the Rust-dev mailing list