Я бы сказал, что если вы хотите жестко закодировать такое поведение, вам лучше не использовать объектно-ориентированное программирование. Просто реализуйте его как функции, вызывающие другие функции.
(«такое поведение», как я понял: если вызов foo2
изнутри кода, который был вызван как super#foo1
, то должен вызываться именно foo2
из реализации суперкласса, а не из более «конкретные» реализации из подклассов)
Это самый простой и понятный и понятный способ продолжить: программные функции, которые делают то, что вы хотите.
Или вы должны объяснить себе и нам: зачем вам ООП? Причина этого не указана в тексте вопроса. Зачем создавать foo1
и foo2
методы, а не независимые функции? (Помимо foo1
и foo2
, у вас могут быть некоторые объекты, классы и методы в вашей программе, где это уместно).
Интересно, возникает ли этот вопрос в сравнении с другими языками? 1016 *
Если вы знаете другой язык ОО, странно, что вы хотите «такое поведение» от ООП: это не поведение, ожидаемое, скажем, в Java или C ++, потому что они используют концепцию таблицы виртуальных методов, которая связана с каждый объект во время выполнения, поэтому при вызове метода в вашей программе он отправляется во время выполнения для реализации этого метода, фактически связанного с объектом. Итак, вкратце: всякий раз, когда вы используете выражение вызова метода в своей программе, вы обязуетесь придерживаться этого принципа нахождения реализации метода («позднее связывание») , на что указывает gasche. Хотя все еще ср. различия между OCaml и языками, реализованными с помощью таблицы виртуальных методов, на которую указывает Ники Йошиучи.
Формализация всего обсуждения доступных и желаемых поведений
Хотя то, что вам нужно, может не соответствовать ожидаемому и доступному поведению во многих популярных языках ОО, это возможно и может быть реализовано в некоторых конкретных системах ООП, если кто-то имеет доступ к внутренним компонентам реализации ООП.
Скажем, если в какой-то реализации, super
- это структура, содержащая таблицу методов суперкласса (к которой можно вернуться при разрешении вызова метода для текущего объекта), а методы - это функции, которые должны получать объект ( таблица методов) в качестве 1-го аргумента, затем, чтобы выполнить то, что вы хотите, можно написать super.foo1(super, y)
.
(Мне действительно интересно, существуют ли реализации ООП, внутренние компоненты которых доступны программисту и которые позволяют выполнять такой вызов.)
Принимая во внимание, что обычное поведение ООП будет выражаться в этой системе как this.foo1(this, y)
(где this
- таблица методов для текущего объекта.)
Ваш вызов OCaml super#foo1 y
или Java super.foo1(y);
переводится в эту "мою" систему как super.foo1(this, y)
. (Хотя по-прежнему сравниваем различия, указанные Ники Йошиучи между OCaml и такими языками, как Java, реализованными с помощью таблицы виртуальных методов.)
Вы видите разницу между 3 случаями.
Приложение. Ищете языки, которые бы работали таким образом
Хм, PHP мог бы быть языком, где такое поведение было бы возможно, но:
- только при программировании на уровне класса (статические методы), но не на уровне объекта;
- только когда вы жестко кодируете какое-то странное «позднее статическое связывание» при вызовах функции:
#!/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);
?>
Модель ведет себя в некотором смысле как стандартные объекты OO с виртуальными методами, а Bar как вы хотели :
$ ./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
$
(Кстати, использование parent::
вместо Foo::
не приведет нас к желаемому поведению.)
Я не понимаю смысла безумных спецификаций связывания PHP, таких как static::
, которые имеют некоторый эффект только для статических методов (то есть, программирования на уровне класса).
Аналогичный пример C ++ по умолчанию не дает поведения на уровне объектов OO:
#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;
}
- дает желаемое поведение:
$ ./a.out | head -10
bar2
foo1
foo2
foo2
foo2
foo2
foo2
foo2
foo2
foo2
$
даже без какого-либо специального спецификатора при вызове функции в коде для Bar::foo2()
, поэтому нам это не интересно.
А как насчет статических методов Java? .. (Они отличаются от C ++ и дают намвиртуальное методоподобное разрешение вызовов функций по умолчанию?)