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
signature.asc
Description: This is a digitally signed message part
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev