I like virtual functions. They're not for everything, and stylistically,
traits are almost always a better solution. However, they can be nice to
reduce code bloat. See how the LLVM devs managed to share a good amount of
code for their SmallVector class thanks to the magic of virtual functions:

http://llvm.org/docs/doxygen/html/classllvm_1_1SmallVector.html

Not sure if it deserves a whole keyword, but a way to do this efficiently
would be nice.

  - Clark


On Tue, Mar 11, 2014 at 3:51 PM, Maciej Piechotka <uzytkown...@gmail.com>wrote:

> On Tue, 2014-03-11 at 14:37 -0500, Evan G wrote:
> > ... Why didn't they just extend Number? (Or, at worst, that was a bad
> > design decision on Oracle's part, by choosing to make the Float class
> > final)
> >
> > Either way, I don't see how that's a fault of the language.
> >
> >
>
> I don't remember - maybe they had, but it wouldn't solved the problem.
> And Float is final - and even if it hadn't been it wouldn't solve the
> problem at all. Assume that Float is not final and they did extended
> Number.
>
>  - Platform P provides interface PI and object PO (say Number and Float)
>  - Component A provided and required interface AI and object AO
> extending PO and implementing AI and PI
>  - Component B provided and required interface BI and object AO
> extending PO and implementing BI and PI
>
> Now you cannot pass object AO to component B as it requires BI. You need
> either:
>  - Provide adapter from AI to BI (or other way round) which implements
> AI, BI and PI
>  - Each time convert from AO to BO when you transfer between interfaces
> In proposed interface there would be only second option due to single
> inheritance.
>
> On the other hand with traits:
>  - Platform P provides interface PI and object PO
>  - Component A provides and requires interface AI and implements AI for
> PO (there is no need for adding AI as PO is 'open' for trait
> implementation)
>  - Component B provides and requires interface BI and implements BI for
> PO (there is no need for adding BI as PO is 'open' for trait
> implementation)
> The user needs to do:
>  - Nothing. Everything works out of the box
>
> And before you ask - component A and B were 2 different libraries for
> which the Oracle interfaces were insufficient.
>
> Best regards
>
> >
> > On Tue, Mar 11, 2014 at 2:35 PM, Maciej Piechotka
> > <uzytkown...@gmail.com> wrote:
> >         On Tue, 2014-03-11 at 19:09 +0000, Bill Myers wrote:
> >         > I see a proposal to add "virtual struct" and "virtual fn" in
> >         the workweek meeting notes, which appears to add an exact copy
> >         of Java's OO system to Rust.
> >         >
> >         > I think however that this should be carefully considered,
> >         and preferably not added at all (or failing that, feature
> >         gated and discouraged).
> >         >
> >         > The core problem of "virtual functions" (shared by Java's
> >         classes, etc.) is that rather than exposing a single public
> >         API, they expose two: the API formed by public functions, and
> >         the API formed by virtual functions to be overridden by
> >         subclasses, and the second API is exposed in an inflexible and
> >         unclean way.
> >         >
> >         > A much better way of allowing to override part of a struct's
> >         behavior is by defining a trait with the overridable
> >         functionality, and allowing to pass in an implementation of
> >         the trait to the base class, while also providing a default
> >         implementation if desired.
> >         >
> >         > Another way is to have the "subclass" implement all the
> >         traits that the "base class" implements, include a field of
> >         the "base class" type, and then direct all non-overridden
> >         functionality to the "base class" (here syntax sugar can be
> >         easily added to eliminate the boilerplate, by automatically
> >         implementing all non-implemented trait functions by calling
> >         the same function on the base class field).
> >         >
> >         > These approaches can be combined, as the first approach
> >         allows to change the "inside" behavior of the base class,
> >         while the second one allows to put extra behavior "around" the
> >         base class code.
> >         >
> >         > The fact that OO using virtual functions (as opposed to
> >         traits) is a bad design is one of the crucial steps forward of
> >         the design of languages like Go and current Rust compared to
> >         earlier OO languages, and Rust should not go backwards on
> >         this.
> >         >
> >         > Here is a list of issues with virtual functions:
> >         >
> >         > 1. Incentive for bad documentation
> >         >
> >         > Usually there is no documentation for how virtual functions
> >         are supposed to be overridden, and it as awkward to add it
> >         since it needs to be mixed with the documentation on how to
> >         use the struct
> >         >
> >         > 2. Mishmashing multiple unrelated APIs
> >         >
> >         > With traits, you could pass in multiple objects to implement
> >         separate sets of overridable functionality; with virtual
> >         structs you need to mishmash all those interfaces into a
> >         single set of virtual functions, all sharing data even when
> >         not appropriate.
> >         >
> >         > 3. No encapsulation
> >         >
> >         > Private data for virtual function implementations is
> >         accessible to all other functions in the struct.
> >         >
> >         > This means for instance that if you have a virtual function
> >         called "compute_foo()" that is implemented by default by
> >         reading a "foo" field in the base class, then all other parts
> >         of the base class can access "foo" too.
> >         >
> >         > If anything else accesses mistakenly "foo" directly, which
> >         it can, then overriding "compute_foo()" will not work as
> >         expected.
> >         >
> >         > If compute_foo() were provided by an external trait
> >         implementation, then "foo" would be private and inaccessible,
> >         eliminating the problem.
> >         >
> >         > 4. Data for overridden implementations left there in a
> >         "zombie" state.
> >         >
> >         > In the above example, if you override "compute_foo()", the
> >         foo variable in the base class will no longer be used, yet it
> >         will still be present in the type and allocated in memory.
> >         >
> >         > 5. Inability to statically dispatch
> >         >
> >         > With a trait implementation, you can pass the concrete type
> >         as a generic parameter, allowing static dispatch.
> >         >
> >         > If you instead call an overridable virtual function, then
> >         you can't dispatch that statically at all (unless you add
> >         cumbersome syntax for that).
> >         >
> >         > 6. Adds a ton of unnecessary complexity to the language
> >         >
> >
> >
> >         7. Harder interoperability. For example I've encountered at
> >         least 2
> >         Float interfaces for Java from 2 different libraries (both
> >         trying to
> >         abstract over Float) which I need to use in one of my projects
> >         (long
> >         story) - either one needed to have an adapter or there was a
> >         need to
> >         convert float to float. In total there were 3 32-bit floats
> >         representation in single function counting also the float.
> >         With traits
> >         they would just add implementation to Java's float.
> >
> >         Best regards
> >
> >         _______________________________________________
> >         Rust-dev mailing list
> >         Rust-dev@mozilla.org
> >         https://mail.mozilla.org/listinfo/rust-dev
> >
> >
> >
> >
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev@mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
>


-- 
Clark.

Key ID     : 0x78099922
Fingerprint: B292 493C 51AE F3AB D016  DD04 E5E3 C36F 5534 F907
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to