
Go and Rust – objects without class - usea
https://lwn.net/SubscriberLink/548560/26d15e832d21a483/
======
usea
I've been developing medium-to-large projects in mostly C# over the past two
years. One thing about my style that has changed over that course of time is
that I almost never use inheritance anymore. When I was in school, it was my
primary tool for code reuse, but now I find it conflates solutions to
different problems, as well as hampering readability.

My style now is small classes with a few, small methods each and lots of
composition. I find it easier to reason about code, separate functionality,
and reuse pieces. Also, placing unrelated state in separate classes really
discourages a lot of the common mistakes with OOP.

Admittedly I don't do as much reading on the subject as I should. I am
probably discovering things that were common knowledge 25 years ago. Maybe
this is a common road that developers take. That's fine with me.

Rust's and Go's OOP style appeals to me quite a bit. I have only written small
things in those languages, so I'm not exactly well-versed in what larger
projects look like. Before reading this article, I wasn't able to put into
words what bothered me about the style of inheritance in languages I've used
up until now.

~~~
noblethrasher
Same here. I used to look for places to use inheritance but now only inherit
from abstract classes, seal everything else by default, and mark all of my
fields readonly.

------
evincarofautumn
The value of Go and Rust, I think, is that they are object-oriented languages
that try to avoid conflating classes with types.

If you think of a type as a set of possible values, then a subclass is
actually a supertype—a superset of the possible values of its parent class—and
likewise a superclass is a subtype. The “is-a” relationship is saying “for all
instances I of X, I is an instance of Y” which is essentially the definition
of superset. That is what the Liskov Substitution Principle is about.

In C++ and other languages with support for object-oriented programming, a
subclass is not necessarily a supertype: virtual functions can throw “I don’t
make sense in this derived class”. And a supertype is not necessarily a
subclass: templates offer the benefit of the doubt when it comes to static
interfaces.

This mismatch leads, in my experience, to interfaces that are ill-specified at
best and buggy at worst—so it’s nice to see those issues addressed.

~~~
riffraff
I am not sure the issue of “I don’t make sense in this derived class” is
solved by decoupling types and inheritance.

For example, given the article's GO code:

    
    
        type file interface {
    	Read(b Buffer) bool
    	Write(b Buffer) bool
    	Close()
        }
    

my first thought was: wait, not all files are writable, that interface is ill
specified.

I do think subtyping and subclassing should be different things, but it's not
a panacea against bad specifications.

~~~
fauigerzigerk
I think this points to a seperate issue as well: Often times we have a choice
to express the same thing through types or through state. As the influence of
functional languages grows, we tend to choose types more often.

It wouldn't be surprising to have a ReadOnlyFile type and a ReadWriteFile
type. This can easily be justified because an individual file object doesn't
need to change its read/write property after it has been created. But
conceptually, files can be written to, just not always.

Another example makes that clearer. Adults can do things that minors can't.
So, for instance, a signContract() method would have to go on the Adult type
not on the Person type. But people grow older, so at any point in time some
objects conceputally change their type from Minor to Adult.

Technically this is not a difficult problem to solve. But it shows the
disconnect between our natural language concepts and the ever more type
centered way of modelling we use in modern software design.

~~~
mseepgood
> As the influence of functional languages grows, we tend to choose types more
> often.

FP does not imply static types. See Lisp and its dialects. Don't confuse the
Haskell way of doing things with FP in general.

~~~
fauigerzigerk
My point isn't a formal one but rather an observation about software design
trends.

More imporantly though, what FP does in both its dynamically and statically
typed incarnations is to prefer (and sometimes enforce) immutability.

Immutable objects support a much more type centered view of the world.
Theoretically, you could have something like a VehicleAtFullSpeed type
(dynamic or static) because the speed attribute of an individual object never
changes.

------
mixedbit
I've been recently watching Structure and Interpretation of Computer programs,
where it is demonstrated that first class functions and assignment operator
with nested scope are enough to implement object oriented system.

The simplest example given is a Counter object. Translated from Lisp to
Javascript it goes like this:

    
    
          function make_counter() {
            var val = 0;
            function get() {
              return val;
            }
            function inc() {
              val += 1;
            }
            return [get, inc]  
          }
        
          function get_count(counter) {
            return counter[0]();
          }
        
          function inc_count(counter) {
            counter[1]();
          }
        
          var counter = make_counter();
          console.log(get_count(counter).toString());
          inc_count(counter);
          inc_count(counter);
          console.log(get_count(counter).toString());
    

This gives polymorphism (you can define make_fast_counter() that increases by
2 and still use get_count() and inc_count() with it) and encapsulation (you
can not decrease the count).

~~~
Jach
From [http://people.csail.mit.edu/gregs/ll1-discuss-archive-
html/m...](http://people.csail.mit.edu/gregs/ll1-discuss-archive-
html/msg03277.html):

The venerable master Qc Na was walking with his student, Anton. Hoping to
prompt the master into a discussion, Anton said "Master, I have heard that
objects are a very good thing - is this true?" Qc Na looked pityingly at his
student and replied, "Foolish pupil - objects are merely a poor man's
closures."

Chastised, Anton took his leave from his master and returned to his cell,
intent on studying closures. He carefully read the entire "Lambda: The
Ultimate..." series of papers and its cousins, and implemented a small Scheme
interpreter with a closure-based object system. He learned much, and looked
forward to informing his master of his progress.

On his next walk with Qc Na, Anton attempted to impress his master by saying
"Master, I have diligently studied the matter, and now understand that objects
are truly a poor man's closures." Qc Na responded by hitting Anton with his
stick, saying "When will you learn? Closures are a poor man's object." At that
moment, Anton became enlightened.

------
discreteevent
From a high level programming in Go looks to me to be very like programming
with Microsoft's COM. It's interface oriented, no inheritance. You could say
that this is the purest form of OO if you take Alan Kay's viewpoint that the
emphasis should be on the messages and not the object. In COM you have
QueryInterface and in Go you have interface matching and casting.
QueryInterface or an interface cast is like a hinge between dynamic and static
typing. You get great flexibility but still preserve your abstractions in that
you never depend on an implementation. Of course you can do this in, say, java
by using instanceof to match against an interface but the difference with COM
and Go is that it is a primary mechanism and so the code written in the
language tends to use this pattern a lot. i.e. It's encouraged.

See this example from Russ Cox:

<https://groups.google.com/forum/#!msg/golang-> nuts/Rj5t1h_ztxI/Fgs6HfLqMHAJ

------
pocketstar
I interpreted the title 'Go and Rust' as in 'go and make some iron-oxide'
evidence that I am a mechanical engineer and programming is just a hobby.

------
metajack
This is a good article, although I'm not sure its appropriate to post a
subscriber link.

~~~
strmpnk
It seems like it's allowed explicitly by LWN: "The following subscription-only
content has been made available to you by an LWN subscriber. Thousands of
subscribers depend on LWN for the best news from the Linux and free software
communities. If you enjoy this article, please consider accepting the trial
offer on the right. Thank you for visiting LWN.net!"

~~~
drothlis
"Where is it appropriate to post a subscriber link? Almost anywhere. Private
mail, messages to project mailing lists, and blog entries are all appropriate.
As long as people do not use subscriber links as a way to defeat our attempts
to gain subscribers, we are happy to see them shared."

\-- <https://lwn.net/op/FAQ.lwn#slinks>

~~~
justincormack
It is probably preferable to the free link being posted a week later as it
makes people aware of the subscription.

