Skip to main content
GameDev.net gamedev.net
🔒 Locked

Is there a name for this construct?

Started by uutee May 16, 2006 at 4:22 AM 5 replies 1.5k views
Original Post
uutee
uutee
Hi, In object oriented programming languages we can often do this: void myfunc(Paintable p) { p.paint(); } I.e we specify a *required* *interface* that the argument object must support. This immediately raises a question: are there *statically* *typed* languages which support requiring *multiple* interfaces for the argument object to support? E.g void myfuncCleanup(p : Paintable, Closeable) { p.paint(); p.close(); } Is there a name for this kind of construct? Do any statically typed languages support it? What are the most common ways of faking it it traditional "single-interface" languages? Thanks! -- Mikko
joanusdmentia
joanusdmentia
Multiple inheritence does this. Not all languages support multiple inheritence though, but they sometimes support multiple interface inheritence (for example, C#). For example in C#:
interface IPaintable { void paint() {} }interface ICloseable { void close() {} }interface IPaintableClosable : IPaintable, ICloseable {}void myfuncCleanup(IPaintableCloseable p) { p.paint(); p.close(); }


It's not quite as flexible as requiring a single parameter to provide an implementation for multiple interfaces, but it'd be quite unusual that you'd genuinely want to mix-n-match interfaces like that. Alternatively, your function can simple 2 references, each implementing one of the required interfaces. This would provide even greater flexibility, making the need for the 'middle ground' approach of yours unnecessary.
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The nly verdict is vengeance; a vendett o
Zahlman
Zahlman
Quote:
Original post by joanusdmentia
Multiple inheritence does this. Not all languages support multiple inheritence though, but they sometimes support multiple interface inheritence (for example, C#). For example in C#:
*** Source Snippet Removed ***

It's not quite as flexible as requiring a single parameter to provide an implementation for multiple interfaces, but it'd be quite unusual that you'd genuinely want to mix-n-match interfaces like that. Alternatively, your function can simple 2 references, each implementing one of the required interfaces. This would provide even greater flexibility, making the need for the 'middle ground' approach of yours unnecessary.


At the possible expense of extra complexity - managing two objects (and possibly a binding between them?) instead of one. The suggested language feature is something I've thought of myself, and it's just another example of doing things "anonymously", which many scripting languages have shown to be immensely useful. If I write "paintable closable p" in a theoretical language that supported it, I would presumably know what I was doing, and not want the compiler to check/complain about a missing interface representing the union of those two interfaces. And it certainly is useful - in a language where integers are first-class objects (or at least auto-boxed), you might label them as strict-weak-ordered (a refinement of comparable, in turn a refinement of equality-comparable), assignable, multiplicative, etc. I.e., all the various mathematical operators and "common" member functions belong to several "groups", and some objects implement various subsets of them (a matrix has a meaningful scalar product, square and even exponentiation, but not a sine, to the best of my knowledge). You wouldn't want to have combinatorial explosion in user-declared union-interfaces, just for the benefit of full type (I would say "capability" is a more appropriate term) checking.

There is one complication: operator overloads can lead to ambiguities, and the compiler therefore has to insist that either overloads also exist to handle the ambiguous cases (unless it can be statically proven that that the type in question doesn't exist), or have some other scheme for resolving the conflict. I have the former in mind for my own programming language design:

// Using C++ style syntax, which my language wouldn't, but just for the// sake of familiarity...int foo(can_wibble x);int foo(can_wobble y);// Error: no definition of foo(can_wibble can_wobble z)int foo(_exact_type bar);// No extra errors: the capabilities of exact_type are known, and only the// _exact_type type can "implement" the _exact_type type. However, it is// possible that the interface "exact_type" is also generated and could be used// to represent all things LSP-substitutable for _exact_type, in which case// more overloads might be necessary (unless exact_type is a refinement of// can_wibble and/or can_wobble).


It also adds, at least for a naive implementation (I'm trying to think of a good solution), the problem that you can no longer have unnamed parameters (it's ambiguous whether the last token in a parameter specification is a name or a possibly-nonexistent capability specification).
JuNC
JuNC
OCaml can do this:

let myfunc p =  p#paint ()let myfunc_cleanup p =  p#paint ();  p#close ()let pobj = object  method paint () = (*do_something*) ()  endlet pobj2 = object  method paint () =  (*do_something*) ()  method close () = (*cleanup*) ()  end(*These are fine:*)let _ = myfunc pobjlet _ = myfunc pobj2let _ = myfunc_cleanup pobj2(*This fails to compile:*)let _ = myfunc_cleanup pobj


Try to compile the above:

File "test.ml", line 26, characters 23-27:This expression has type < paint : unit -> unit > but is here used with type  < close : unit -> 'a; paint : unit -> 'b; .. >Only the second object type has a method close


Note I've not included class definitions but the above is perfectly legal OCaml code.

EDIT:

I realise this doesn't look like quite what you wanted, the example is poor since Paintable may as well be a subclass of Closeable. OCaml supports structural subtyping which means the interface is defined by the methods called and not (necessarily) by any given class definition.
MENTAL
MENTAL
Python can do exactly what you are looking for. When you pass an object to a function, it doesn't care about the object type so long as it supports all the methods you're going to call on it. For example (taken from "The Best Software Writing I"):

class Cat:    def speak(self):        print "meow!"class Dog:    def speak(self):        print "woof!"class Bob:    def greet(self):        print "Hello, please to meet you!"    def speak(self):        print "My name is Bob."def command(pet):    pet.speak()pets = [ Cat (), Dog (), Bob () ]for pet in pets    command(pet)


In that example, the "command" function doesn't care what type of object it recieves or how far down in the class definition the "speak" function is defined. If it has a "speak" function it will be called, and if not it will throw an exception (which can be easily caught).

edit: gah, you said staticly typed. Unfortunatly, what you are attempting to do is one of the reasons why dynamicly/weakly typed languages are so popular :)
Rebooted
Rebooted
Structural subtyping has this property. OCaml has structural subtyping, so it works there. Python/Ruby have duck typing, which is essentially structural subtyping, but in a dynamic system.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.