From: Sean O'Dell Date: 2003-11-22T02:43:58+09:00 Subject: Re: "stereotyping" (was: Re: Strong Typing (Re: Managing metadata about attribute types) ) On Friday 21 November 2003 02:28 am, Peter wrote: > > I am not sure exactly how Haskell works, but it sounds like perhaps > > fulfillment could occur through a form of aliasing, although calls could > > still be made to the method required by its original name. Calls doing > > that would actually route through the aliased method. Since this only > > involves the interface mechanism, and would be just another method to > > Ruby, this could work, sure. > > > > It could look like: > > > > class AnyClass > > def method(parameters) implements someothermethod > > end > > > > ... which would allow someothermethod to be fulfilled in the interface > > requirement, but the method would actually be called method. You could > > call either and get the same method. Until the method was subbed later > > on by its real name, in which case method would just be a method (and > > would still exist). > > Actually it's rather an application of the adapter pattern, which is an > interface problem and which could benefit from support in interface > declaration. But my problem rather lies in the fact that two libraries > both expect an object to have a method with a certain name - but the same > for both - but they expect different behavior from it. You can always > rename your own methods, but not those that a library expects. (Though you > can "adapt" those a library offers through something like aliasing). Oh, I see. You know, I think I know of a script language that did that. Actually, what it had were a sort of virtual method system, where you could have the same method name implement several variations of itself, but each one was tagged to a "context." When you call the method, you could call it in the default context and the default method would execute, or put the object into some other context and call the method, and an entirely different method would execute. The method names could be the same; they were only differentiated by their context. > > Interfaces allow that, but wouldn't be able to provide for it. You could > > certainly still handle method_missing calls for methods that are outside > > the scope of an interface because an object would only need to fulfill an > > interface, not be strictly bounded by it. I doubt we could create an > > interface mechanism that actually made use of method_missing, though. I > > think when it comes to interfaces, things get a little bit strict. But > > the freedom is still there to work outside of them. If a class can't > > implement a method without handling it through a call to method_missing, > > I think we have to say that method cannot fulfill an interface. > > My point is just that the wolves will pick on this because it decreases > flexibility in the sense that any method which expects an object > implementing a certain interface can't be passed such a proxy. If it's > just your own code, you can just decide not to use the interface (which is > basically what you say above, right? Or only use part of it), but anyone > using your interfaces in a library API would restrict the flexibility for > the users. Basically implementing an interface is saying that you are duck > typing, but the check doesn't manage all of duck typing. I know it's a shortcoming, but the whole notion of interfaces has lots of things that restrict what you can do. That's why you can mix them in anywhere, and all the usual Ruby rules still apply. But I think where might want both a run-time method morphing scheme AND to be able to promise it through an interface, I really think we would have to come up with a name aliasing scheme (perhaps that was your suggestion originally, I think). It would serve the purpose. But let's also not forget that interfaces wouldn't DOMINATE Ruby. They're just there to provide a little help to code sharers. I doubt it can be all things to all people. > > I think when it comes down to the nuts and bolts of it, those sorts of > > things are cool ideas to patch in down the road. I think the basics of > > it will work, and this sort of thing will crop up now and again, but Matz > > or someone would be able to zip in a patch to do that pretty easily. > > Well, just saying it would be nice to think of this possibility up front, > that it's possible and easy to do. I'm sure Matz is a much better > programmer than anyone of us, but not all is easily done. I think if the interface mechanism were there, it would appear as a short hop to adding in an "alternate context" sort of mechanism. Right now, that's a couple steps ahead, so it's seems far-off, but with interfaces working, it wouldn't. > > There are two ways this is partially covered: > > > > One, and I know this is the "not my job" answer: interfaces should be > > well-defined enough to separate Input from Output to begin with. I think > > with poorly designed interfaces, you're going to have trouble. > > OK, this is where I don't agree with you. If you don't allow refining the > granularity (which superinterfacing is supposed to do), you'll always end > up being less flexible than duck typing as it is now. This has nothing to > do with poor design. A good design is flexible, maintainable, adaptable, > but it can't provide for all future needs. Can you guarantee that if you > write an interface, that it's the smallest useable subset of > functionality? But interfaces are for making contracts. Contracts are like plans. You can't design it poorly up-front, start making promises, then rescind the promises. The interfaces (when used, they ARE optional) are supposed to be a layout of what something can and can't do. Ruby provides flexibility enough by itself, interfaces should provides firmness. > > Two, interfaces can be subbed in my proposal, so you could subclass an IO > > string interface from a base IO interface. > > > > But as to superclassing, since the original interface designer lumped > > Input and Output into one interface, what you are really talking about is > > bypassing the interface requirements that methods might have. Instead of > > looking at it as superclassing an interface, look at it as shoving any > > old object past a requirement. I think there should be a mechanism for > > that as well. Flexibility should always be paramount. I just don't see how you can make a contract that says "this does this" and then pass in an object which has superclassed that contract, removed some portions of it, then push the object to a parameter which requires the original contract. Even with a superclassing mechanism, it's a lie; the method is not receiving what it has asked for. So, since it's a lie, why not just make a way to push any object past a requirement. If someone is going to do that, they're taking the risk. Something might blow up, or if they know for some good reason it won't, they can try it. What I mean is, if an interface designer lumps Input and Output together, and provides a method that requires an object which fulfills the InputOutput contract, how can you pass an object which only partially fulfills this requirement? My feeling is, you should be able to, but since you're giving it an object that doesn't give it 100% of what it asks for, just shove the object in there the old-school Ruby way and hope for the best. No need to write up a superclass. Write a whole new interface for Input and one for Output, and then just shove objects that fulfill those interfaces past InputOutput requirements. > > Unless I misunderstood your use of superclassing the interface. Correct > > please if I'm wrong. > > I will. Suppose someone design a library with Input and Output as provided > interfaces. Then classes will emerge that implement these interfaces, > right. The separation in Input and Output is based on the functionality of > the library, logically, right? When I use this library, and I would need > only an interface that only requires a subset of say the Input interface. > This is possible, right? I have several options. Either I create my own > interface with a subset of the methods of the Input interface, but then > any class implementing this Input interface can't be passed as something > implementing your interface, or at least not as such, while duck typing > allows for this. If you allow for superinterfacing (i.e., defining a > subset of methods in a separate interface), you have this flexibility > automatically. I see where you're driving at. The interface is not compared through method signatures. There are methods which require InputOutput by name, not by a set of method signatures, so superclassing to Input and thus generating a unique signature of methods would not make those methods happy. They still just want objects which fulfill the InputOutput contract. Again though, my experience is: when you design the interfaces, just design them right. But looking at the method signature idea: I think if you matched interfaces based on method signatures, you're talking about having methods which all have their own (potentially) uniquely generated requirement signature. That means that every object passed in every parameter would have to be checked to ensure each object passed had all the right methods. That's a lot of run-time overhead. It's much simpler just to compare the parameter types (named interfaces or none) to the interface description to see that they match the requirements for that method. It would be much, much faster just doing that, and if you designed the interfaces correctly, you get the same reassurance. Sean O'Dell