multiple inheritence - how to dynamically decide method?

According to this page:

tads.org/t3doc/doc/sysman/multmeth.htm

There exists a means of making the determination of which overridden version of a method to call be a late decision that happens at runtime based on the type of the object actually being passed as a parameter.

However, upon trying it it seems the compiler is telling me that despite the name multi-method, this doesn’t actually work on methods (functions inside object classes). It only works on global functions, not on actual methods.

Is this true? Ideally I want to do a thing like this:

class Game: object
  doTurnDaemon()
  {
    getCurPlayer().takeGameTurn(self);
  }
;
class PokerGame: Game
;
class BlackjackGame: Game
;

class PokerActor: GameActor
  takeGameTurn(PokerGame g)
  {
  }
;
class BlackjackActor: GameActor
  takeGameTurn(BlackjackGame g)
  {
  }
;

cardSharpWilly: PokerActor, BlackjackActor
;

The idea is that when any Game object derived from Game, such as a PokerGame or Blackjackgame, runs the code seen above in doTurnDaemon(), on an actor who is multiply inherited from both PokerActor and BlackJackActor as in the example cardSharpWilly shown above, it gets the right version of the method takeGameTurn() because of the types listed in the function’s argument list.

But the above syntax does not work. It seems the compiler is insisting that doing a thing like this:

takeGameTurn(BlackjackGame g)

is illegal in a method. It’s only allowing it in a global function, so I have to implement this by putting the functions outside the classes like so:

class Game: object
  doTurnDaemon()
  {
    takeGameTurn( getCurPlayer(), self);
  }
;
class PokerActor: GameActor
;
takeGameTurn(PokerActor p, PokerGame g)
{
}

class BlackjackActor: GameActor
;
takeGameTurn(BlackjackActor p, BlackjackGame g)
{
}

Is this true? Or am I just not understanding the syntax error I’m getting and there is a way to make a multi-method an actual method inside a class?

I believe that analysis is essentially correct. I think part of the reason they’re nevertheless called multi-methods is that (as I read the TADS 3 System Manual) they’re functionally similar to methods in what they do. As the System Manual puts it:

"So, to summarize, a multi-method with one typed parameter is basically just an alternative syntax for writing a regular method.

This equivalency is helpful because it makes it easier to understand what happens when you have more than one typed parameter. The multi-method system applies the same logic to each typed parameter, choosing the one that’s the best fit to the object according to its class inheritance."

Part of what that quotation is saying, I think, is that declaring the method:

modify Thing
   foo()  { /* do stuff here */ }

Is effectively equivalent to defining the multi-method:

foo(Thing obj)
{
   /* do stuff here */
}

Given that, it wouldn’t actually make sense to define a multimethod as belonging to a single class or object, since the whole point is that it’s meant to handle definitions like:

PutIn(Thing obj, Container cont)
{
}

Would this be a method of the Thing class or the Container class? In my understanding the whole point of the construct is that it acts like a method of both, so it wouldn’t really make sense to define it on either.

But there’s plenty of cases in OOP where when what you want is code that handles “an X does something with a Y” you have to make a sort of arbitrary decision whether you’ll implement that as a method of class X that takes an argument of type Y, or a method of class Y that takes an argument of type X. You don’t generally see people in that case making the decision “well, since it could be done either way, let’s do it neither way and put the method entirely outside both X and Y.”

Anyway, this is an irrelevant topic of wishing for things to be different than they are. What matters is that yes it’s true I have to do it this way because it isn’t implemented to work the way I was trying to do it originally. That means I’ll have to be a bit verbose and explanatory in my documentation since most users of TADS don’t do multi-methods and I can’t quite hide the complexity away entirely from them.

You should submit a feature request for this. It may not be possible to implement but it can’t hurt to ask.