From: Robert Feldt Date: 2002-02-04T18:29:04+09:00 Subject: Re: Subclassing vs Subtyping (partly OOP vs FP) On Mon, 4 Feb 2002, Dave Thomas wrote: > 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 agree that his example is not very strong (even if you agree that a "set is a bag with no duplicates" it doesn't follow that a set fulfills all of a bags contracts; he changes the semantics of a test function and then makes a hen out of the fact that a bag and a set reacts in different ways to the change) and would not generally be a problem in Ruby. However, I found it relevant since it made me think about why this would not happen in Ruby. My conclusion was not so much that this is a question of Ruby or not but about whether I think enough about the contracts involved. Also that it could be a good thing to make the implicit protocols more explicit (by more "formal" unit tests?). And that one should try to code "anonymously" as much as possible (ie. sending messages and not directly instantiating classes unless necessary), ie. following the rule "The body of your methods should assume as little information as possible about the objects it acts on, but no less". Cheers, Robert Ps. In the paper the author changes the method def foo(a, b, c) ab = a.clone ab += b ab <= c end into def foo(a, b, c) ab = Bag.new ab += a ab += b ab <= c end and builds his case from the fact that a set will give the same results as a bag for the first one but not for the second one. The "right" way to do it would probably be def foo(a, b, c) (a + b) <= c end which would assume the least.