Equivalent to late static binding(PHP) in other popular languages

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test(); // Outputs "B"
?>

I want to get an equivalent in Java...so something like

class A {
    public static void who(){
        System.out.println("A");
    };

    public static void test(){
        who(); //<<< How to implement a static:: thing here???
    }
}

class B extends A {
     public static void who(){
        System.out.println("B");
     };

     public static void main(String[] args){
        B.test(); // Outputs "A" but I want "B"
     }
}

I want the who() call inside A::test to resolve as in PHP 5.3 by calling B::who .

EDIT: I know there is no "standard way" of doing this in most popular languages. I'm looking for hacks and such. Also, is this possible in C/C++, or any other popular OOP language?

This is not for any real design on anything. I'm just being curious.


Not possible in Java. (At least not without ugly reflection hacks.)

I encourage you to rethink your design and rely on proper objects.

Related question:

  • Can I override and overload static methods in Java?
  • Edit: B.test() will (or can at least according to spec) be compiled into a call to A.test() , so there's no way to discover how the call was made from within A.test() . In other words, there's no way to let the behaviour of A.test depend on if it was called through A.test() or B.test() .

    Since you're asking out of curiosity, here's AFAIK the closest "solution".

  • Overload test with a test(Class<?> c) which takes as argument the class which defines the intended who method.
  • Hide (note that you can't override) test() in class B .
  • And change the implementation of A.test slightly.
  • In code:

    class A {
        public static void who() {
            System.out.println("A");
        }
    
        public static void test() {
            test(A.class);
        }
    
        public static void test(Class<?> c) {
            //who(); //<<< How to implement a static:: thing here???
            try {
                c.getMethod("who").invoke(null); // Call static who on given class.
            } catch (Exception e) {
            }
        }
    
    }
    
    public class B extends A {
         public static void who(){
            System.out.println("B");
         }
    
         public static void test() {
             test(B.class);
         }
    
         public static void main(String[] args){
            A.test(); // Outputs "A"
            B.test(); // Outputs "B"
         }
    }
    

    It seems that the compiler generates a call to B.test in the bytecode even though B doesn't declare a method named test .

    Bytecode of main method:
    
    invokestatic #5 = Method B.test(()V)
    return
    

    Given the names of a class and method ( "B" and "who" ) you can easily use reflection to call the method. So the question becomes

    Can you extract B by combining the call stack and bytecode inside A.test ?

    You'll need to use the return address stored on the stack to locate the call to B.test in the bytecode and extract the declared call. There are plenty of bytecode manipulation libraries, but I don't know if any of them allow you to tie that to the execution stack in the JVM.


    You can't override static methods in java.

    http://geekexplains.blogspot.co.uk/2008/06/can-you-override-static-methods-in-java.html

    链接地址: http://www.djcxy.com/p/82426.html

    上一篇: 从Python代码中的方法打印当前调用堆栈

    下一篇: 相当于其他流行语言中的晚期静态绑定(PHP)