Да знаю, знаю, что нет в go ООП. Но есть эмуляция, и я хочу решить задачу, которая на плюсах решается
тривально привычно:
#include <iostream>
struct FooBar {
virtual void Foo() = 0;
virtual void Bar() = 0;
};
// Этот класс имплементирует интерфейс методами по умолчанию
class foo : public FooBar {
public:
// Этот метод будет переопределяться в наследниках
void Foo() override {
std::cout << "foo::Foo" << std::endl;
}
void Bar() override {
Foo(); // Ожидается, что здесь будет вызван метод наследника
std::cout << "foo::Bar" << std::endl;
}
};
// А вот и наследник с переопределённым методом
class bar : public foo {
public:
void Foo() override {
std::cout << "bar::Foo" << std::endl;
}
};
int main() {
FooBar* fb = new bar();
fb->Bar();
delete fb;
return 0;
}
И всё работает как и ожидалось:
bar::Foo
foo::Bar
https://ideone.com/1Lf02l
Теперь go:
package main
import "log"
type FooBar interface {
Foo()
Bar()
}
type foo struct{}
func (*foo) Foo() {
log.Println("foo::Foo")
}
func (f *foo) Bar() {
f.Foo() // Ожидается, что здесь будет вызван метод "наследника"
// Но похоже, что инфорация о типе здесь безвозвратно утеряна.
log.Println("foo:Bar")
}
type bar struct{ *foo }
func (*bar) Foo() {
log.Println("bar::Foo")
}
func NewFooBar() FooBar {
return &bar{&foo{}}
}
func main() {
fb := NewFooBar()
fb.Bar()
}
Но нет:
2009/11/10 23:00:00 foo::Foo
2009/11/10 23:00:00 foo:Bar
Program exited.
https://go.dev/play/p/23zNfIZ3Swq
И как же быть?
Пока приходится копировать реализацию Bar() в каждом "наследнике". А это ну... моветон какой-то. Должен же быть способ, не может же быть что так тупо всё и задумывалось.
Гугление проводит к таким ресультатам:
https://www.reddit.com/r/golang/comments/28garc/what_is_the_preferred_way_to_provide_a_default/
Но там нет вызова методов, который я хочу.