From: Lewis Perin Date: 2002-02-08T10:04:28+09:00 Subject: Re: Subclassing vs Subtyping (partly OOP vs FP) Dave Thomas writes: > Lewis Perin writes: > > > > http://okmij.org/ftp/Computation/Subtyping/ > > > > The above was posted ten days ago and so far the silence has been > > fairly deafening. I found the site Robert Feldt mentions quite > > compelling and was hoping that some true Ruby adepts would have a lot > > to say about it. > > To be honest I was not particularly stirred by the article. It became > apparent during the lead-in that the choice of basing a Set on a Bag > was wrong, and everything else fell out from that (it's the old Circle > < Ellipse or Ellipse < Circle debate). > > It's also not to relevant to Ruby, as Ruby's types are based on > implicit protocols, not classes. In Ruby, you typically sublcass to > get behavior, not interface, so these issues just don't arise. You > might choose to delegate a Set to a Bag, or you might choose to have a > general collection mixin tha both Set and Bag could use, but you'd be > unlikely to subclass one from the other. > > It's a difficult habit to break. When you're used to C++ and Java, it > seems natural to think of everything in terms of class hierarchies. > But after programming in Ruby for a while, I find that I'm writing > fewer and fewer deep class trees. I took the liberty of forwarding this message plus the one by Robert Feldt that immediately followed it to Oleg, the author of the subclassing/subtyping site. (I didn't forward the later followups, not because they weren't interesting but because they didn't really reply to Oleg's work.) His response can be found below my sig. /Lew -- Lew Perin / perin@acm.org -------Oleg's response follows----- Hello! Thank you indeed for forwarding me follow-ups! I do want to comment on the follow-ups. I am replying to you, so that you will catch errors and wrong assumptions I may have made about Ruby. I understand that some of my points may be considered inflammatory. The last thing I want is to incite a flame war or to tell people what they should or should not be using. If you do find my reply relevant, please free to post it, entirely ort in parts. I'm afraid the follow-ups do not go beyond picking on the C++ example, which is indeed contrived. The first follow-up also correctly noted that article is about the old "Circle < Ellipse or Ellipse < Circle debate". Yet the article tries to do more. For example, the article actually shows that Set < Bag! (see below). The second part of the article tries to discuss subtyping (not subclassing!) regardless of the implementation language. In that respect the conclusions may be relevant to Ruby as well. I must mention that the need to clarify the article and to point out general issues shows that the web pages are poorly written. In this respect, I'd like to point out a paper http://pobox.com/~oleg/ftp/papers/Subtyping-OOP.ps.gz which, IMHO, is phrased a bit better. Section 3 of the paper considers Bags and Sets in the most general way -- from two different perspectives. One approach is to regard Bags and Sets as _objects_, that is, as entities with a state and the reactive behavior. We show that such objects are not subtypes of each other. Note that we're talking about _subtyping_ rather than subclassing, derivation or other implementation details. Bag and Set can be just objects that happen to accept a common set of messages. In the later section, we consider Bags and Sets as entities _without_ a state (distinct from their identity) and _without_ a reactive behavior. In this approach, a Set is indeed a subtype of a Bag: a Set _is-a_ Bag, every function that accepts Bags can be given a Set instead without any change in behavior, a Set maintains every invariant of a Bag -- and it is still a Set. The paper and the web site then go into excruciating details to explain that the stated assertions indeed hold, all at the same time. I'm afraid it is in this jungle of details where I lost my reader. Although Section 4 of the paper uses C++ to define _non-object_ Bags and Sets, the conclusion hold regardless of the implementation language. Section 4.4 attempts to show that, by consider the problem mathematically and designing an isomorphism between Bags and Sets on one hand and certain sets of integers on the other hand. The paper reaches a conclusion that it may be beneficial to broaden our view and consider that not everything is an object, and not everything should be an object. For example, distributed programming is easier if processes exchange passive messages rather than active messages (i.e, objects). It's easier to specify and reason about a (passive, immutable) data structure than to specify and reason about a behavior. See also http://www.mozart-oz.org/lists/oz-users/0431.html I specifically do not say that we should completely forgo objects. I'm saying that object-less design ought to be on the table when considering possible approaches to a problem. It's up to a developer to select reactive entities or passive entities, or the mixture of the two -- based on that developer's experience and the problem at hand. BTW, the second follow-up mentions contracts. It is often claimed that Design by contract can guard against improper inheritance. Design by contract enforceable at run time is useful as a regression testing tool -- but no more than that. The problem is how to specify the contract precisely enough. Given a Stack abstract data type, what is a post-condition of a 'push' method? The post-condition should account for two facts -- that the pushed element becomes the top of the stack, _and_ that the push method is free of all other side effects. The latter requirement is far more difficult to specify -- let alone to effectively compute. Another good example to contemplate is the post-condition of a random number generator. What is the contract of the rand() function? Is it something you can easily compute/verify during each invocation of rand()? BTW, this paragraph is from an article that I started to write last year, and put on indefinite hold after having written 10 pages or so. Thank you again for your kind message! Oleg