Сообщение Re[2]: ООП не получается от 27.06.2023 15:17
Изменено 27.06.2023 15:17 Doom100500
Re[2]: ООП не получается
Здравствуйте, Буравчик, Вы писали:
Б>Ты хочешь иметь дефолтную реализацию, и переопределить ее в наследниках?
Здравствуйте, Буравчик, Вы писали:
Б>Ты хочешь иметь дефолтную реализацию, и переопределить ее в наследниках?
Да, но есть нюанс
. Надо вызвть наследника из базы. Я перепишу стартовый промер, чтобы намерения стали понятнее:
Это не работает, и даже понятно почему: нет никакого наследования и виртуальных таблиц, есть композиция.
И это нормально работает в объектно — ориентированных языках с виртуальными методами и настоящим наследованием.
То, что я хочу должно выглядеть (для go) примерно так:
Но так в go нельзя. Но что-то похожее обещали в go2 (но это, как всегда, неточно):
https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md
Зато можно вызывать базу из наследников. Сейчас у меня работет такой код:
Но это значит, что метод DoAction() должен копироваться без изменений во все наследники.
Сначала я смирился и запилил 3-х наследников. Но потом, когда месяца через два спал пилить четвёртого, мой внутренний перфекционист взбунтовался — мало ли что я забуду скопировать.
Возможно я что-то делаю не так, но я так и не смог придумать как избавиться от копирования. Всё ночь снились дженерики и даже генерация кода.
Сдаётся мне, что должен быть какой-то идиоматический путь избежать такой копипасты, но я его не вижу...
Б>Ты хочешь иметь дефолтную реализацию, и переопределить ее в наследниках?
Здравствуйте, Буравчик, Вы писали:
Б>Ты хочешь иметь дефолтную реализацию, и переопределить ее в наследниках?
Да, но есть нюанс
package main
type Behavor interface {
CheckCondition() bool //Это могло быть и приватным, но пусть клиентский код тоже сможет проверять условие
DoAction()
}
type defaultBefavior struct{}
func (*defaultBefavior) CheckCondition() bool {
panic("Not implemented!!!")
}
func (b *defaultBefavior) DoAction() {
if !b.CheckCondition() { //Дёрнуть наследника
return
}
// Do actual action
// Общий код для всех наследников
}
type stupidBehavior struct {
*defaultBefavior
}
func (b *stupidBehavior) CheckCondition() bool {
//Проверяем внутреннее состояние - разное для всех наследников
// и, в соответсвии с этим, возвращаем результат
return true
}
func NewStupidBehavior() Behavor {
return &stupidBehavior{
defaultBefavior: &defaultBefavior{},
}
}
func main() {
st := NewStupidBehavior()
st.DoAction() // panics
}Это не работает, и даже понятно почему: нет никакого наследования и виртуальных таблиц, есть композиция.
И это нормально работает в объектно — ориентированных языках с виртуальными методами и настоящим наследованием.
То, что я хочу должно выглядеть (для go) примерно так:
func (b Befavior) DoAction() { // здесь сам интерфейс является ресивером
if !b.CheckCondition() { //Дёрнуть наследника
return
}
// Do actual action
// Общий код для всех наследников
}Но так в go нельзя. Но что-то похожее обещали в go2 (но это, как всегда, неточно):
https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md
Зато можно вызывать базу из наследников. Сейчас у меня работет такой код:
package main
type Behavor interface {
CheckCondition() bool //Это могло быть и приватным, но пусть клиентский код тоже сможет проверять условие
DoAction()
}
type defaultBefavior struct{}
func (b *defaultBefavior) doActualAction() {
// Общий код для всех наследников
}
type stupidBehavior struct {
*defaultBefavior
}
func (b *stupidBehavior) CheckCondition() bool {
//Проверяем внутреннее состояние - разное для всех наследников
// и, в соответцвии с этим, возвращаем результат
return true
}
func (b *stupidBehavior) DoAction() {
if b.CheckCondition() {
b.doActualAction()
}
}
func NewStupidBehavior() Behavor {
return &stupidBehavior{
defaultBefavior: &defaultBefavior{},
}
}
func main() {
st := NewStupidBehavior()
st.DoAction()
}Но это значит, что метод DoAction() должен копироваться без изменений во все наследники.
Сначала я смирился и запилил 3-х наследников. Но потом, когда месяца через два спал пилить четвёртого, мой внутренний перфекционист взбунтовался — мало ли что я забуду скопировать.
Возможно я что-то делаю не так, но я так и не смог придумать как избавиться от копирования. Всё ночь снились дженерики и даже генерация кода.
Сдаётся мне, что должен быть какой-то идиоматический путь избежать такой копипасты, но я его не вижу...
Re[2]: ООП не получается
Здравствуйте, Буравчик, Вы писали:
Б>Ты хочешь иметь дефолтную реализацию, и переопределить ее в наследниках?
Да, но есть нюанс
. Надо вызвть наследника из базы. Я перепишу стартовый промер, чтобы намерения стали понятнее:
Это не работает, и даже понятно почему: нет никакого наследования и виртуальных таблиц, есть композиция.
И это нормально работает в объектно — ориентированных языках с виртуальными методами и настоящим наследованием.
То, что я хочу должно выглядеть (для go) примерно так:
Но так в go нельзя. Но что-то похожее обещали в go2 (но это, как всегда, неточно):
https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md
Зато можно вызывать базу из наследников. Сейчас у меня работет такой код:
Но это значит, что метод DoAction() должен копироваться без изменений во все наследники.
Сначала я смирился и запилил 3-х наследников. Но потом, когда месяца через два спал пилить четвёртого, мой внутренний перфекционист взбунтовался — мало ли что я забуду скопировать.
Возможно я что-то делаю не так, но я так и не смог придумать как избавиться от копирования. Всё ночь снились дженерики и даже генерация кода.
Сдаётся мне, что должен быть какой-то идиоматический путь избежать такой копипасты, но я его не вижу...
Б>Ты хочешь иметь дефолтную реализацию, и переопределить ее в наследниках?
Да, но есть нюанс
package main
type Behavor interface {
CheckCondition() bool //Это могло быть и приватным, но пусть клиентский код тоже сможет проверять условие
DoAction()
}
type defaultBefavior struct{}
func (*defaultBefavior) CheckCondition() bool {
panic("Not implemented!!!")
}
func (b *defaultBefavior) DoAction() {
if !b.CheckCondition() { //Дёрнуть наследника
return
}
// Do actual action
// Общий код для всех наследников
}
type stupidBehavior struct {
*defaultBefavior
}
func (b *stupidBehavior) CheckCondition() bool {
//Проверяем внутреннее состояние - разное для всех наследников
// и, в соответсвии с этим, возвращаем результат
return true
}
func NewStupidBehavior() Behavor {
return &stupidBehavior{
defaultBefavior: &defaultBefavior{},
}
}
func main() {
st := NewStupidBehavior()
st.DoAction() // panics
}Это не работает, и даже понятно почему: нет никакого наследования и виртуальных таблиц, есть композиция.
И это нормально работает в объектно — ориентированных языках с виртуальными методами и настоящим наследованием.
То, что я хочу должно выглядеть (для go) примерно так:
func (b Befavior) DoAction() { // здесь сам интерфейс является ресивером
if !b.CheckCondition() { //Дёрнуть наследника
return
}
// Do actual action
// Общий код для всех наследников
}Но так в go нельзя. Но что-то похожее обещали в go2 (но это, как всегда, неточно):
https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md
Зато можно вызывать базу из наследников. Сейчас у меня работет такой код:
package main
type Behavor interface {
CheckCondition() bool //Это могло быть и приватным, но пусть клиентский код тоже сможет проверять условие
DoAction()
}
type defaultBefavior struct{}
func (b *defaultBefavior) doActualAction() {
// Общий код для всех наследников
}
type stupidBehavior struct {
*defaultBefavior
}
func (b *stupidBehavior) CheckCondition() bool {
//Проверяем внутреннее состояние - разное для всех наследников
// и, в соответцвии с этим, возвращаем результат
return true
}
func (b *stupidBehavior) DoAction() {
if b.CheckCondition() {
b.doActualAction()
}
}
func NewStupidBehavior() Behavor {
return &stupidBehavior{
defaultBefavior: &defaultBefavior{},
}
}
func main() {
st := NewStupidBehavior()
st.DoAction()
}Но это значит, что метод DoAction() должен копироваться без изменений во все наследники.
Сначала я смирился и запилил 3-х наследников. Но потом, когда месяца через два спал пилить четвёртого, мой внутренний перфекционист взбунтовался — мало ли что я забуду скопировать.
Возможно я что-то делаю не так, но я так и не смог придумать как избавиться от копирования. Всё ночь снились дженерики и даже генерация кода.
Сдаётся мне, что должен быть какой-то идиоматический путь избежать такой копипасты, но я его не вижу...