Earlier quoted context omitted.
So rust traits are effectively/functionally abstract classes with restricted functionality and a different implementation?
Sort of. The closest thing in C++ would be concepts. That is, even using traits in this way is the minority case; they're more usually used for monomorphized, statically dispatched code. But, given the case where you want dynamic dispatch, then in a sense, they are, yes.
Classes Considered Harmful [pdf]
101–110 of 129 posts
Re: Classes Considered Harmful [pdf]
#102Having used C++, Java, C#, Python, Ruby, NewtonScript, Dylan, Scheme, and various other languages "in anger" I can say that in general I agree with the author's frustrations. My favorite (as in most flexible, least boilerplate) approaches to object-oriented programming have been: - NewtonScript's frames with prototype inheritance. Allows "objects" to consist of very small data structures that point to ROM objects and…
In addition to Dylan, Julia also allows multiple dispatch via generic functions. I have found this approach to multiple dispatch leads to code that's much easier to reason about and maintain. My use case is a tensor library where the tensors have a single interface but various storage backend types, which 'interact' with each other. It doesn't make sense to define these interactions through methods belonging to only…
Re: Classes Considered Harmful [pdf]
#103Earlier quoted context omitted.
Sort of. The closest thing in C++ would be concepts. That is, even using traits in this way is the minority case; they're more usually used for monomorphized, statically dispatched code. But, given the case where you want dynamic dispatch, then in a sense, they are, yes.
Right. I suppose in Rust you generally use variants and pattern matching when dynamic dispatching is required.
It really just depends on what exactly you're trying to do.
Re: Classes Considered Harmful [pdf]
#104Earlier quoted context omitted.
Superior composability with simpler semantics and sounder type systems. Class hierarchies are inherently unfriendly to strong, sound type systems. Interface composition isn't. Composing interfaces is clean and straightforward. Composing classes isn't, and you run into things like the diamond problem.
Classes do not imply inheritance. Classes are a means of defining an interface, albeit a heavy one. The statement that it is better to separate data and behavior is far from self-evident IMO, and I would be very interested to understand why this is such a deeply held belief. Seriously, why?
Personally speaking, it's just a lot easier. I could go on about various theoretical justifications, but at the end of the day it's just easier. This probably has something to do with the fact that you don't really gain anything by defining data and behavior together, but you do lose flexibility by coupling those possibly orthogonal concerns.
Re: Classes Considered Harmful [pdf]
#105Earlier quoted context omitted.
Superior composability with simpler semantics and sounder type systems. Class hierarchies are inherently unfriendly to strong, sound type systems. Interface composition isn't. Composing interfaces is clean and straightforward. Composing classes isn't, and you run into things like the diamond problem.
Classes do not imply inheritance. Classes are a means of defining an interface, albeit a heavy one. The statement that it is better to separate data and behavior is far from self-evident IMO, and I would be very interested to understand why this is such a deeply held belief. Seriously, why?
Re: Classes Considered Harmful [pdf]
#106And, given all the use cases I have, I'd be amazed if one class of language can do it all. I'm guessing it's impossible.
It's way better for my engineering team to know how to use a bunch of different specialized tools, and how to use them together, than to focus on one type of tool.
Re: Classes Considered Harmful [pdf]
#107When you have classes, you have subclassing, and subclassing means two different things at the same time. First, subclasses are the subtyping operation. If you want type B to be a subtype of A, B must subclass A. Second, they provide code reuse via inheritance.
Each of those things is useful, but there's no reason to tie them together. In fact, modern best practices in OO say to favor interfaces and delegation over subclassing, and that's precisely because it separates those two concerns.
As far as I can tell, this is what the paper was getting at - separating delegation of implementation from subtyping. Since this is already what OO best practices suggest, why is it controversial?
Re: Classes Considered Harmful [pdf]
#108Re: Classes Considered Harmful [pdf]
#109Amount of boilerplate one needs to implement "good" OO design is just horrendous. For example, in C++, previously we had rule of 3. Now its rule of 5! Just having a virtual abstract interface means almost half dozen lines of boilerplate! Even in managed languages such as C# or Java, it would require significant effort to create, say, read-only version of collection given a read-write collection. One of the goal for l…
E.g., @property (readonly) NSString* myName;
Re: Classes Considered Harmful [pdf]
#110Earlier quoted context omitted.
Classes do not imply inheritance. Classes are a means of defining an interface, albeit a heavy one. The statement that it is better to separate data and behavior is far from self-evident IMO, and I would be very interested to understand why this is such a deeply held belief. Seriously, why?
It's not always true, by any stretch of the imagination. Closures couple data and behavior and most (though not all) functional programmers consider closures to be pretty central to FP. I'd add that closures are hard to use in that way without allocating, which is why I think one potentially reasonable argument against coupling data and behavior is performance-driven, but that's a more subtle argument that ignores co…
The use of closures in functional programming is an implementation detail, not a fundamental aspect of the underlying theory, and closures only "couple" data and behavior in the very literal sense that it is a function that happens to point to some data under the hood, not in the syntactic or semantic sense we're referring to when we say that OOP classes couple behavior and data.
A closure in a pure language can't couple to data any more than a lambda expression without free variables (from the programmer's perspective), because they can have the exact same type and semantics.
In other words, there's no semantic difference between "f = \x . x + 2" and "f = let y = 2 in \x . x + y" even though the latter is a closure in the absence of inlining.