6

Is it possible for a method to know the type of the method it is called under? So for example in the following object orientated psuedo code:

Instance io = new InstanceSubclass();
io.doStuff();

Is there a language that allows doStuff() to know that it was called as an Instance?

The question arose out of the fact the Java does not provide any kind of support for interface name clashes, for example if you create a class that implements interfaces A and B that both have a method signature such as void doWork() would it be possible for the body of doWork() to do something similar to the following :

public void doWork() {
    Class<?> context = getMethodCallContext();
    if(context == InterfaceA.class) {
        doAsInterfaceA();
    }
    else if(context == InterfaceB.class) {
        doAsInterfaceB();
    }
    else {
        // Shenanigans and error handling
    }
}

I am not planning to write any code that takes advantage of this feature as to do so reeks of an anti-pattern waiting to happen, I only want to know if it CAN be done, if so which languages permit it?

ahjmorton
  • 671
  • 4
  • 10

4 Answers4

5

What you described is achievable via Aspect-Oriented Programming (AOP). It won't be as straightforward as in your example, but you can get the requested behaviour.

AOP has implementations in different languages; AspectJ being one of the most mature one. I will give you an example using AspectJ even though I don't want to go to in too much detail.

To implement the behaviour:

1) Create a pointcut that will intercept all the calls to the public void doWork() method.
[pointcut conflictingMethodIsExecuted(): execution(public void doWork()]

2) Create an advice around this pointcut. Within the advice, you can get the context; just as you have specified in your example. The JoinPoint will serve you that information.
[joinPoint.getThis() // returns the context]

3) With that information, the advice sets a certain parameter and lets the public void doWork() run. The method takes a look at that parameter and decides what to do.

I assume the question was a bit theoretical so this answer also goes along the same line. I can provide more details about the solution in AspectJ if you choose to take this path.

Guven
  • 914
  • 5
  • 18
3

In C# you just do:

 void InterfaceA.doWork()
 {
 }

 void InterfaceB.doWork()
 {
 }

So there are no real shenanigans involved.

The calling function needs to identify which doWork() is intended:

Instance io = new InstanceSubclass();
((InterfaceA)io).doStuff();

See this page for more details.

Peter K.
  • 3,828
  • 1
  • 23
  • 34
  • There is a catch: these methods cannot be public. The above function definitions would not compile. – Mike Nakis Jan 02 '12 at 08:39
  • True... but the effective accessibility still seems to be `public`. Any pointers as to why this is, @MikeNakis ? – Peter K. Jan 02 '12 at 14:16
  • @PeterK.: I think the accessibility of explicitly implemented interface methods will be the same as the accessibility of the interface itself. iirc – quentin-starin Jan 02 '12 at 14:21
  • @qes: Thanks! Implementing a "private interface" seems like an oxymoron somehow, though. :-) – Peter K. Jan 02 '12 at 14:23
  • @PeterK.: They would be `internal`, and that would simply be a contract you want a class to implement, but not expose outside the assembly. Maybe not so common in a standard LOB app, but if its a component library meant for use by others its much more common to use internal interfaces for .. well .. internal details ;-) – quentin-starin Jan 02 '12 at 14:28
  • The effective accessibility is not `public`. If you had only one `doWork()` method, you still would not be able to access it with `io.doWork()`, because it is not visible. When you cast `io` to `InterfaceA`, then the method becomes visible because we are now dealing with `InterfaceA`, whose methods are all public by definition, and not with `InstanceSubclass`, whose `doWork()` method is private. – Mike Nakis Jan 02 '12 at 14:35
  • @MikeNakis: Thanks! It seems like a little subversive to have `void interfaceA.doWork()` have public accessibility (when cast). – Peter K. Jan 02 '12 at 14:37
  • @PeterK. This answers my question exactly, C# has the ability to fufil two sets of interfaces with the static types being known during the method body. It would be awesome if you do so for even a normal method call, so for example a subclass would know if it had been called it's parent or as itself. All very theoretical – ahjmorton Jan 02 '12 at 23:19
1

I don't see an interface method name clash here. There would be a clash in the case of multiple inheritance, but that is a different class relationship.

In your example you have two interfaces both of which require that you implement a void doWork method with no parameters. What the method needs to do should be independent of which Interface is used to call the method. If there is a conflict, then it lies in the interface specification, or the design of the class to use the two interfaces with differing expectations of the doWork method.

More complicated method signatures could result in methods with the same name but differing signatures, in which case the signature would be used to differentiate between the two methods.

BillThor
  • 6,232
  • 17
  • 17
0

You can get exactly this effect in Java by overloading a method:

  public void doStuff(InterfaceA object) {
    // stuff for InterfaceA
  }

  public void doStuff(InterfaceB object) {
    // stuff for InterfaceB
  }

And call it as follows:

  if (object instanceof InterfaceA) {
    doStuff((InterfaceA)object)
  } 
  else if (object instanceof InterfaceB) {
    doStuff((InterfaceB)object);
  }

This is also pretty performant: all the calls will be statically determined by the compiler so you really only have the instanceof / casting overhead (which is pretty minimal).

mikera
  • 20,617
  • 5
  • 75
  • 80