Path: utzoo!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!husc6!think!barmar From: barmar@think.com (Barry Margolin) Newsgroups: comp.object Subject: Re: inheritance and `type loss' Message-ID: <40602@think.Think.COM> Date: 13 Jul 90 05:45:31 GMT References: Sender: root@Think.COM Distribution: comp Organization: Thinking Machines Corporation, Cambridge MA, USA Lines: 50 In article sra@ecs.soton.ac.uk (Stephen Adams) writes: >If V+V is not a roman (but an integer, 10) then some >information has been lost. I don't agree. + is a function that maps from to integer. When roman inherits this operation, it can generally only deal with the "integerness" of roman numbers. The integer class doesn't know that the roman class exists, so how could integer.+ produce a roman? Virtual functions can allow base classes to operate at the descendents' levels in some ways, but it can get pretty difficult to delegate all the right things. In your example the + function isn't being overridden by the derived class, so what virtual functions might it call that would do the right thing? And in the V+1 and 1+V cases, how would this generic plus know whether to call the virtual function of the left or right argument (I think CLOS multimethods allow the priority of the arguments to be specified in the generic function definition), or how do you make the order irrelevant? Yes, information is lost. Consider what would happen if the subclass also has additional data, rather than just overriding a method. For instance, suppose there were a flag slot in the roman class that indicated whether it should be printed in the old style ("IIII" rather than "IV"). How could integer.+ know how to fill in this instance variable? I suppose it could let this default, but you're still losing information, since you'd expect that two romans with the same style should sum to another with that style. Actually, that wouldn't be a good way to implement the two styles, but the object-oriented way also has a similar problem. In this case, we'd make another subclass of integer called "old-roman", which also only overrides the image function and inherits integer.+. Now, what would you expect IIII+IV to return? In fact, it would be reasonable to make old-roman a subclass of roman, but it would be just as reasonable to go the other way. Therefore, even if we were to define a mechanism where the result of the addition were the most recent common ancestor of the two arguments, there's no inherent reason why IIII+IV should pick one or the other as the result type. And what if the most common ancestor were an abstract class; for instance, suppose there were an intermediate class, roman-without-4, which would be abstract because it doesn't know how to display 4 (it would have a pure virtual function image4). So, in general, using an inherited operation tends to be an information-losing mechanism. It's easy to move up the inheritance hirarchy, but hard to move back down. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar