I would say that if you want to write this behavior hard, it is better not to use object-oriented programming. Just implement it as functions that call other functions.
("this behavior", as I understand it: if you call foo2 from inside the code that was called as super#foo1 , then you should call foo2 from the implementation of the superclass, and not from the more "specific" implementations from subclasses)
This is the easiest and cleanest way: software features that do what you want.
Or should you explain to yourself and to us: why do you need OOP? The reason for this is not indicated in the question text. Why use the foo1 and foo2 methods rather than independent functions? (In addition to foo1 and foo2 , there may be some objects and classes and methods in your program).
I wonder if this question arises compared to other lnaguages
If you know another OO language, it is strange that you want “this behavior” from OOP: this is not the behavior expected, for example, in Java or C ++, because they use the concept of a virtual method table that is associated with each object during execution, so when you call a method in your program, it is sent at run time to implement this method, which is actually associated with the object. So, in short: when you use an expression to invoke a method in your program, you agree to adhere to this principle of finding a method implementation ("late binding") , as pointed out by Gasche. Although still cf. differences between OCaml and languages implemented in the table of virtual methods noted by Niki Yoshiuchi.
Formalizing the entire discussion of available and desired behaviors
Although what you want may not be the expected and accessible behavior in many popular OO languages, it is possible and can be implemented in some specific OOP systems, if you have access to the internal functions of OOP.
Say, if in some implementation of super there is a structure containing a table of methods of the superclass (to return to the resolution of the method call for the current object), and methods are functions that should receive the object (method table) as the 1st argument, then execute what you want is to write super.foo1(super, y) .
(Actually, I am wondering if there are OOP implementations whose internals are accessible to the programmer and which allow such a call to be made.)
While normal OOP behavior would be expressed in this system this.foo1(this, y) (where this is the method table for the current object.)
Your call to OCaml super#foo1 y or Java super.foo1(y); converts to this "my" system as super.foo1(this, y) . (Although the differences noted by Nicky Yoshiuchi between OCaml and languages such as Java implemented using the virtual method table still coincide.)
You see the differences between the three cases.
Application. Search for languages that will work this way
Hmm, PHP may be a language where this behavior is possible, but:
- only on programming at the class level (static methods), and not at the object level;
- only when you hardcode the weird "late static bindings" when calling the function:
#!/usr/bin/php <?php class Foo { public static function foo1($y) { echo "foo1\n"; static::foo2($y-1); } public static function foo2($y) { echo "foo2\n"; if ($y > 0) static::foo2($y); else echo "end\n"; } } class Bar extends Foo { public static function foo2($y) { echo "bar2\n"; if ($y > 0) Foo::foo1($y); else echo "endbar\n"; } } class Model extends Foo { public static function foo2($y) { echo "model2\n"; if ($y > 0) static::foo1($y); else echo "endmodel\n"; } } Model::foo2(3); Bar::foo2(3); ?>
The model behaves in the sense of standard OO objects with virtual methods, and Bar as you would like :
$ ./test-force-super-binding.php | head -20
model2
foo1
model2
foo1
model2
foo1
model2
endmodel
bar2
foo1
foo2
foo2
foo2
foo2
foo2
foo2
foo2
foo2
foo2
foo2
$
(By the way, using parent:: instead of Foo:: will not lead us to your desired behavior.)
I don’t understand what crazy PHP binding specifications, such as static:: , that have some effect only for static methods (like class-level programming).
The C ++ analog example does not, by default, specify the level behavior of an OO object:
#include<iostream> class Foo { protected: static void foo1(int y) { std::cout << "foo1" << std::endl; foo2(y-1); } public: static void foo2(int y) { std::cout << "foo2" << std::endl; if (y > 0) foo2(y); else std::cout << "end" << std::endl; } }; class Bar: public Foo { public: static void foo2(int y) { std::cout << "bar2" << std::endl; if (y > 0) foo1(y); else std::cout << "endbar" << std::endl; } }; int main() { Bar::foo2(3); return 0; }
- this gives your desired behavior:
$ ./a.out | head -10
bar2
foo1
foo2
foo2
foo2
foo2
foo2
foo2
foo2
foo2
$
even without a special qualifier when calling a function in the code for Bar::foo2() , so we are not interested.
What about Java static methods? .. (are they different from C ++ and give default permission to call functions by default?)