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
···
On Friday 21 November 2003 02:28 am, Peter wrote: