Лукавство в шаблонном методе на Go
В Go наследование реализации отделено от полиморфизма. Можно создать «наследника структуры», сделав первое её поле безымянным. Можно у «родительской структуры» и у «дочерней» написать одноимённые методы. Но методы «родительской» структуры не будут полиморфно вызывать методы «дочерней», а будут статически вызывать свои методы, не смотря на то, что «родительская» создана не сама по себе, а как первое поле «дочерней».
Поэтому такой пример шаблонного метода на Go просто так не перепишется:
class Employee {
private String name;
Employee(String name) {
this.name = name;
}
final String greeting() {
return "Hello, my name is " + this.name + ", I am a " + post();
}
protected abstract String post();
}
class Manager implements Employee {
Manager(String name) {
super(name);
}
protected String post() {
return "manager";
}
}
class Welder implements Employee {
private int degree;
Welder(String name, int degree) {
super(name);
this.degree = degree;
}
protected String post() {
return "сварщик " + degree + " разряда";
}
}А ведь в этом фишка шаблонного метода — в базовом классе можем пользоваться состоянием базового класса и абстрактными методами, определёнными в потомках. (Кстати, на C++ чисто виртуальный метод post() вообще можно объявить private — виртуальные приватные методы в C++ в потомках переопределять можно, но вызывать нельзя. Но это к делу не относится.)
В примере на сайте базовый класс пустой, не имеет данных, что создаёт обманчивую видимость простоты реализации.
Шаблонный метод существенно использует возможность наследования реализации вместе с полиморфизмом, чего в Go нет. На эту ограниченность нужно обратить внимание в примере.
Service d'assistance aux clients par UserEcho
Пример для шаблонного метода выше на Go выглядит примерно так:
package main import ( "fmt" ) type IEmployee interface { post() string } type Employee struct { name string virtual IEmployee } func (this *Employee) greeting() string { return "Hello, my name is " + this.name + ", I am a " + this.virtual.post() } type Manager struct { Employee } func (this *Manager) post() string { return "Manager" } func makeManager(name string) *Manager { result := &Manager{Employee{name, nil}} result.Employee.virtual = result return result } type Welder struct { Employee degree int } func (this *Welder) post() string { return "сварщик " + fmt.Sprint(this.degree) + " разряда" } func makeWelder(name string, degree int) *Welder { result := &Welder{Employee{name, nil}, degree} result.Employee.virtual = result return result } func main() { m := makeManager("Петя") w := makeWelder("Коля", 6) fmt.Println(m.greeting()) fmt.Println(w.greeting()) }Можно запустить: https://play.golang.org/p/ajvp-0iNpbR