Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

For fun I was thinking about how a programming paradigm could differ from OOP and came up with this concept. I don't have a strong foundation in computer science so it might be common place without me knowing it (more likely it's just a stupid idea :)

I apologize in advance for this somewhat rambling question, anyways here goes:

In normal OOP methods and classes are variant only upon parameters, meaning if two different classes/methods call the same method they get the same output.

My, perhaps crazy idea, is that the calling method and class could be an "invisible" part of it's signature and the response could vary depending on who call's an method.

Say that we have a Window object with a Break() method, now anyone (who has access) could call this method on Window with the same result.

Now say that we have two different objects, Hammer and SledgeHammer. If Break need to produce different results based on these we'd pass them as parameters Break(IBluntObject bluntObject)

With a mutating programming language (mpl) the operating objects on the method would be visible to the Break Method without begin explicitly defined and it could adopt itself based on them). So if SledgeHammer calls Window.Break() it would generate vastly different results than if Hammer did so.

If classes are black boxes then mutating classes are black boxes that knows who's (trying) to push it's buttons and can adapt their behavior accordingly.

You could also have different permission sets on methods depending who's calling them rather than having absolute permissions like public and private.

Does this have any advantage over OOP? Or perhaps I should say, would it add anything to it since you should be able to simply add this aspect to methods (just give access to a CallingMethod and CallingClass variable in context)

I'm not sure, might be to hard to wrap one's head around, it would be kinda interesting to have classes that adopted themselves to who uses them though. Still it's an interesting concept, what do you think, is it viable?

Here's some potential dummy code from a game where a player has is damaged by something. In normal OOP most things would instead be passed as parameters to the method whereas here Damage "pulls" the properties it uses. Different? yes, better? perhaps not :)

Class Player
{
    [AccessableBy:Terrain,Player]
    void Damage
    {
        if (#CallingClass has property HitPoints)
        {
            this.health -= #CallingClass.HitPoints;
        }

        if (this.health < 0 && #CallingClass is Terrain)
        {
            ShowMessage("was killed by the environment");
        }
        else if (health < 0 && #CallingClass is Player &&  #CallingMethod is RocketLauncher)
        {
            ShowMessage("was killed with a rocketlauncher by player" + #CallingClass.PlayerName);
        }

    }
}

To reduce if-else statements you could have method overrides based on caller methods and classes

share|improve this question
1  
How is this so different from OOP where one can have classes inherit various methods or override them? As an example, consider classes for rectangle and square where the latter overrides the area computation by being just squaring the input of a side length rather than doing a length times width computation. I'll grant that the permissions may be interesting except that most systems will have separate parts where security is handled in a rather configurable fashion as this tends to be customized to some extent so I question how useful is that for a distributed system. –  JB King Jan 11 '11 at 21:26
3  
Don't virtual functions and inheritance essential do exactly this? –  Pemdas Jan 11 '11 at 21:27
    
The difference is that methods could return different result depending on which class and method calls them. Of course you can get this behavior pretty much with parameters and polymorphism but it would have to be explicitly declared. What you're really doing is moving logic and responsibility from the caller to callee'. Say that you have an Encryption Class, it could encrypt data differently depending on the needs of the caller, kinda lika a built-in factory pattern. –  konrad Jan 11 '11 at 21:34
6  
Is Window 'object' supposed to know all possible 'objects' that might want to break() it? –  Mchl Jan 11 '11 at 21:37
    
I guess it would at least need to know some interfaces, or there might be some kind of ducktyping. If it needed to know the exact types of everyone calling it wouldnt be that useful. –  konrad Jan 11 '11 at 21:38
show 1 more comment

8 Answers

up vote 12 down vote accepted

Let me see if I understand what you're getting at.

In traditional OOP languages like C++ or C#, the action of a method depends on the runtime type of the receiver:

Window w1 = new GlassWindow();
Window w2 = new PlexiglassWindow();
w1.Break(new Brick());
w2.Break(new Brick());

Which method is actually invoked depends on the runtime type, not the compile time type, of the receiver, provided that Break is "virtual".

Languages which have this property are called "single virtual dispatch" languages.

Your proposal is that the action of Break depend also upon the runtime type of the argument. Suppose Break takes an Object:

w1.Break(new Hammer());
w1.Break(new Pillow());
w2.Break(new Hammer());
w2.Break(new Pillow());

and now perhaps four different things happen depending on the runtime types.

This sort of double dispatch operation is very common in things like games, where you want to have different logic for every possible kind of collision: player with laser, laser with laser, laser with player, player with wall, laser with wall...

Languages that have this property are called "double dispatch" languages; languages that can do more than double dispatch are said to be "multiple dispatch".

This is a pretty well-studied area; do a web search on "visitor pattern" to learn more about simulating double dispatch in a single dispatch language.

share|improve this answer
    
Eric, that's not entirely what i mean. It's more like, say that Brick has some method calling Window Break: SomeBrickMethod(){window.Break();} Window's Break Method has two context properties CallingMethod and CallingClass so it's Break method can use that information for conditional purposes or pulling some property out of the calling class/interface, like void Break(){if (Break.CallingMethod is SomeBrickMethod) force = CallingClass.ForceImpact)} –  konrad Jan 11 '11 at 22:19
    
So CallingMethod and CallingClass are always implicitly declared and available for any method and class –  konrad Jan 11 '11 at 22:25
2  
@MattiasK: I don't understand what the difference is between Hammer calling Break and Break "magically" knowing that Hammer called it, and Hammer passing an instance of itself to Break. Aside from possibly details of what the syntax looks like, how do the two scenarios differ? –  Eric Lippert Jan 11 '11 at 22:31
    
I'm not sure myself :) but if methods/classes always implicitly know who calls them that could open up for some higher abstraction/flexibility and interesting possibilities. You wouldn't have as strict method signatures for once perhaps making versioning/refactoring easier. You could go even further and classes knowing what class they're contained in etc. Factory/Visitor patterns etc take care of most of these scenarios but perhaps this would be simpler, perhaps not :) –  konrad Jan 11 '11 at 22:38
1  
@Eric, I don't think that the scenarios do differ from a pure CS perspective... but having "magical" syntax for something can make all the difference in the world from a pragmatic programming perspective. –  JSBձոգչ Jan 11 '11 at 23:28
show 6 more comments

This sounds pretty much like what S4 is doing in R : defining a generic method and then dispatching to a method based on the signature of the arguments, i.e. :

setGeneric("sum", function(x,y) standardGeneric("sum")) 

# method for numeric object with a numeric argument
setMethod("sum", 
          signature=c("numeric","numeric"), 
          function {
             return(x+y)
})

# method for a numeric object with a character argument
setMethod("sum", 
          signature=c("numeric","character"), 
          function {
             return(paste(x,y))
})

# method for a numeric object with all the rest
setMethod("sum",
          signature=c("numeric","ANY"), 
          function {
             return(x)
})

Or I must have misunderstood you completely. In this code the function "sum" will match the given arguments (what you call the caller (first argument) and the callee (second argument) with the signature of the functions. If it can't match, it will match the one where the signature says "ANY".

PS : this is a trivial example, obviously

share|improve this answer
2  
+1: I think the OP should try R or Common Lisp, which has a similar facility for generic methods. –  Larry Coleman Jan 11 '11 at 21:57
    
@Larry: good point about Common Lisp! –  Joris Meys Jan 11 '11 at 22:29
    
R, Common Lisp, Dylan, Clojure ... –  JUST MY correct OPINION Jan 12 '11 at 10:08
add comment

One of main rules in life is not to add extra complexity unless it's needed. The caller in OOP can always pass some parameter that would tell the callee, how exactly the callee must behave. What you want to do is just add an implicit parameter (class/method signature). And what the purpose is?

If some method should react on what the caller is, then just pass the caller's class name / type / whatever explicitly and that's all. With good RTTI this can be done in a handy way - you pass a reference to the caller's object to a callee and callee inspects the type info of the caller object.

share|improve this answer
    
I guess the main concept I thought was interesting is a shift to methods and classes know who's using them and could be "adaptive" using those facts. Not having to declare explicit parameters could make code more flexible, esp if you combine it with ducktyping. I'm a bit unsure of whether it would work practically though :) –  konrad Jan 11 '11 at 22:51
1  
@MattiasK - most callers are written long after the code they call. What use is it for my library to know specifically that it's called by Fred if I never heard of Fred, because Fred won't exist for another 10 years? Adapting to context is fine, but not if you can't understand the context. Run-time dispatch (multiple included) is fine. The parameter provides the context in a way that is explicit enough - the run-time type is as explicit as the value, both hidden behind the same identifier/expression/whatever. –  Steve314 Jan 12 '11 at 4:21
add comment

You can already do this (i.e. finding out who the calling class/method is) in any JVM language by looking at the stack trace. You should have a look at the documentation for the method "getStackTrace" in the Thread class. What you want can be implemented in just a few lines.

share|improve this answer
add comment

Sounds like extension methods.

Except extension methods can only live on static classes. You just want the same idea (a this parameter modifier) for any method.

share|improve this answer
    
Not really, as I said the main difference is that the called method knows who's calling it, and can react accordingly. You don't know that with extensions methods –  konrad Jan 11 '11 at 22:17
    
somewhere you still have to define what the reaction is. –  Pemdas Jan 12 '11 at 4:29
add comment

Your idea sounds similar to:

It turns out that you may not even need implicit parameters for what you're trying to do.

share|improve this answer
add comment

I think what you are suggesting completely breaks the concept of abstraction all together. A function should not have logic based on what function or object called it. The is an implicit dependency there that would be a maintenance nightmare.

share|improve this answer
add comment

This sounds a lot like typeclasses, or, as @Ken Bloom points out, Scala's implicit parameters (which are basically Scala's object-oriented interpretation of typeclasses).

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.