Ну коли так, то бесцельно спорить с вами я вижу смысла ровно ноль :)
Решите, пожалуйста, упражнение без применения наследования, не важно на каком языке, покажите класс!
Суть таких задач ведь не написать идеальное решение (пример все равно стерильно искусственный). Суть — на своем личном опыте понять те или иные концепции, в данном случае самому придти к пониманию, что либо мы используем наследование, либо отходим от ООП. Вы выбрали вариант два, перейдя к процедурному стилю (вынесли общий код во внешнюю процедуру, забив на инкапсуляцию кстати).
А показывать код, объяснять что и для чего, почему оно так а не иначе, разжевывать — абсолютно нецелесообразно. Это как бисер перед свиньями метать — время убъешь, бисер потратишь, а свинья останется свиньей.
Потом я спросил, будет ли объектно ориентированным код, написанный на Go, если там наследование будет не нужно.
Окей. Отвечу. От может быть как объктно-ориентированным, так и нет. Как, например, может быть объектно-ориентирпованным код на С. Целые объектные фрейморки на С есть. Что, однако, не делает этот язык ООП.
По поводу вашего упражнения — плохо. Вы пишете про "код, который рассчитан на наличие методов у самих сущностей", но ваши сущности эти методы не имеют.
Вызов RectShape(1).areaSqrt() вернет что? Бросит ошибку.
Ну а ваше решение упражнения со звездочкой — типичное гоферовское (это не комлимент). Дабы оптимизировать один метод (areaSqrt) что сделали? Правильно, скопипастили все методы из другой сущности и переписали один из них, так что у нас есть сейчас две реализации 'halvedArea'. Короче опять незачет.
Ну мы с вами выяснили, что от поддержки нормального наследования Go отделяет невозможность переопределить метод.
Нет. Это вы себя для себя придумали. В Go есть композиция с автомагической делегацией. Невозможность переопределить метод — наиболее очевидное, "механистическое" отличие.
В целом да (хотя пример очевидно совсем уж искуственный, и наследования в конкретно этом куске нету, ибо оно тут не нужно).
Я для вас выделил кусочек текста, который вы не заметили.
Я не понял в чём сложность вернуть корень из площади, а код вот, пожалуйста )).
Хорошо, а теперь для тренировки основ:
сделайте так, чтобы у самих сущностей *Shape были методы halvedArea и т.п. Ибо сейчас ваш код по сути эквивалентен такому;
(задание со *) сделайте так, чтобы для SquareShape не происходило бесполезного возведения в квадрат а затем извлечения корня. Ибо это а) медленно, б) теряется точность.
И так как от того, чтобы быть ООП языком Go отделяет возможность переопределить метод, получается, что именно эта возможность ухудшила бы язык. Ну, то есть Template Method это выходит антипаттерн, а не паттерн вовсе.
Вы неверно истолковали мою мысль. Решение многих задач через наследование может быть проще (быстрее и легче запилить), но дороже в плане поддержки в долговременной перспективе. Особенно если у вас большой проект, и много "вчерашних студентов" и просто не очень сильных программистов. Читайте "проще натворить фигни".
Ну вот этот код он объектно ориентированный?
В целом да (хотя пример очевидно совсем уж искуственный, и наследования в конкретно этом куске нету, ибо оно тут не нужно). Попробуйте теперь в качестве упражнения добавить сюда метод "вернуть удвоенную площадь". А потом, в качестве усложненного упражнения, добавить метод "вернуть корень из площади" и подумать, как все это можно оптимизировать/улучшить.
если бы в Go было бы какое-то наследование, то Go был бы объектно-ориентированным даже по вашему "старому" определению?
Ну да. И стал бы при этом хуже, нежели сейчас.
А вообще ООП сейчас проникло повсюду, очень удобный концепт получился.
Ага, настолько удобный, что дизайнеры языков от него совершенно сознательно отказываются (дада, я про Go или, скажем, Rust). Но дабы не потерять популярность "у народа" вынуждены писать, "ой… ну да и нет...". А то иначе плебс не примет.
И код, в котором не использовалось наследование не был объектно ориентированным кодом?
Может быть. На JS вполне можно писать в процедурном стиле.
Итого, инкапсуляция есть, полиморфизм есть, почему тогда Go это не объектно ориентированный язык?
Наследование забыли =)
На самом деле полиморфизм есть во всех более-менее высокоуровневых языках. Аналогично с инкапсуляцией. Я уже приводил ссылку на статью на вики — есть пример инкапсуляции на C.
Так что если следовать вот такому "новому" определению ООП (где вместо 3 принципов оставили только 2), то Go выходит объектным. Но тогда получится, например, что и Haskell тоже ООП-язык… Да блин, тогда не-ООП языки вообще останутся? :))
А вот extends появилось сравнительно недавно, но ООП в джаваскрипте было и до этого.
Ага-ага. А процедурное программирование — это программирование с использованием процедур. А структурное программирование — это программирование с использованием структур. А функциональное — это когда программирование с использованием функций.
Я вам не хамлю. Я констатировал факт того, что вы забыли свои же недавние фразы.
Следуя оффициальной терминологии в C# именно что generics. Причем "Generic programming" != "Generics".
Прежде чем пороть чушь, пройдите по своей ссылке, и почитайте что в C# именно что generics, и что даже code generation является одним из подходов к Generic programming. И что type erasure не является необходимым атрибутом generic'ов. И вот дабы это наглядно показать, вам привели в пример C#. На что в ответ пошла чушь навроде "В C# те же шаблоны". Глупо и некрасиво.
type erasure запили как компромисс, который позволили по минимум переделывать виртуалку, коих для джавы мнооого. А еще сделать весь старый код совместимым с новой джавой.
Наличие type erasure в обной из реализаций дженериков не означает что оно есть везде.
Это не волнует фанатиков и дураков. Так то народ постоянно стонет и ругается на обработку ошибок в Го (точнее на ее отсутствие). Блин, этож самая популярная тема похейтить сей яызк :D
Я выше написал и лично я не могу вспомнить где мне реально понадобилась функция которая заменяет 3 строки кода.
Ну во-первых, тут три строки. Там три строки… Потихоньку набегает. А во-вторых — а зачем так привязываться к filter? Ведь можно поговорить о более удачных примерах из оригинального пропозала
Там приводят
func Keys(m map[K]V) []K
func Uniq(<-chan T) <-chan T
func Merge(chans ...<-chan T) <-chan T
func SortSlice(data []T, less func(x, y T) bool)
Неужели ни разу не понадобилась фунция Keys?
а написать пару раз фильтр на 3 строки за проект
А, понял. Проекты просто махонькие. Ну тогда норм.
Ну это если функция фильтрует слайсы, то она
"бесполезная". Ну гляньте на примеры из статьи https://blog.golang.org/pipelines, например функцию merge. Как же весло, когда нельзя такую функцию добавить в непонятный пакет, а нужно копипастить по большому проекту!
Мне кажется ваша логика сломалась: с дженериками будет копипаста из-за того, что люди забудут об существующей реализации — это плохо, но без дженериков будет еще больше копипасты — это типо хорошо.
Ну добавите вы проверку. Сделали такую проверку в рантайме, тип не тот, паники нету… Но что дальше? Напечатать в лог "Unsupported!!" и продолжаете выполнение? Т.е. в вашем понимании это "все работает"?
Ну коли так, то бесцельно спорить с вами я вижу смысла ровно ноль :)
Суть таких задач ведь не написать идеальное решение (пример все равно стерильно искусственный). Суть — на своем личном опыте понять те или иные концепции, в данном случае самому придти к пониманию, что либо мы используем наследование, либо отходим от ООП. Вы выбрали вариант два, перейдя к процедурному стилю (вынесли общий код во внешнюю процедуру, забив на инкапсуляцию кстати).
А показывать код, объяснять что и для чего, почему оно так а не иначе, разжевывать — абсолютно нецелесообразно. Это как бисер перед свиньями метать — время убъешь, бисер потратишь, а свинья останется свиньей.
Окей. Отвечу. От может быть как объктно-ориентированным, так и нет. Как, например, может быть объектно-ориентирпованным код на С. Целые объектные фрейморки на С есть. Что, однако, не делает этот язык ООП.
По поводу вашего упражнения — плохо. Вы пишете про "код, который рассчитан на наличие методов у самих сущностей", но ваши сущности эти методы не имеют.
Вызов
RectShape(1).areaSqrt()
вернет что? Бросит ошибку.Ну а ваше решение упражнения со звездочкой — типичное гоферовское (это не комлимент). Дабы оптимизировать один метод (areaSqrt) что сделали? Правильно, скопипастили все методы из другой сущности и переписали один из них, так что у нас есть сейчас две реализации 'halvedArea'. Короче опять незачет.
Нет. Это вы себя для себя придумали. В Go есть композиция с автомагической делегацией. Невозможность переопределить метод — наиболее очевидное, "механистическое" отличие.
Я для вас выделил кусочек текста, который вы не заметили.
Хорошо, а теперь для тренировки основ:
Вы неверно истолковали мою мысль. Решение многих задач через наследование может быть проще (быстрее и легче запилить), но дороже в плане поддержки в долговременной перспективе. Особенно если у вас большой проект, и много "вчерашних студентов" и просто не очень сильных программистов. Читайте "проще натворить фигни".
В целом да (хотя пример очевидно совсем уж искуственный, и наследования в конкретно этом куске нету, ибо оно тут не нужно). Попробуйте теперь в качестве упражнения добавить сюда метод "вернуть удвоенную площадь". А потом, в качестве усложненного упражнения, добавить метод "вернуть корень из площади" и подумать, как все это можно оптимизировать/улучшить.
Воспользоваться можно, переопределить нельзя.
Ну да. И стал бы при этом хуже, нежели сейчас.
Ага, настолько удобный, что дизайнеры языков от него совершенно сознательно отказываются (дада, я про Go или, скажем, Rust). Но дабы не потерять популярность "у народа" вынуждены писать, "ой… ну да и нет...". А то иначе плебс не примет.
Может быть. На JS вполне можно писать в процедурном стиле.
Наследование забыли =)
На самом деле полиморфизм есть во всех более-менее высокоуровневых языках. Аналогично с инкапсуляцией. Я уже приводил ссылку на статью на вики — есть пример инкапсуляции на C.
Так что если следовать вот такому "новому" определению ООП (где вместо 3 принципов оставили только 2), то Go выходит объектным. Но тогда получится, например, что и Haskell тоже ООП-язык… Да блин, тогда не-ООП языки вообще останутся? :))
Ну так и наследование ведь было, называлось prototypal inheritance.
Я поправил, бгагодарностей не надо.
Я этого не утверждал. С моей точки зрения, это как раз тут имеется.
Да. Именно это и имеют в виду — объединение кода и данных. Иные трактовки идут от безграмотности.
Ну разумеется инкапсуляция в джаваскрипте есть.
Наследование там тоже есть, даже ключевое слово extends завезли :D
"И да и нет" != "написано, что Go — ООП язык". Это скорее "а фиг его знает", или даже "ой… ну если придумать свое определение ООП..." :)
Неа, это упаковка данных и кода в одной сущности.
А почему, вы пользуетесь каким-то конкретным определением ООП?
Там это НЕ написано.
Это не связяно с инкапусляцией.
А что обязательно?
Простите, конечно, но вы сравниваете несравнимые вещи: Jmeter не на Go, и там нету Yaml!
Ага-ага. А процедурное программирование — это программирование с использованием процедур. А структурное программирование — это программирование с использованием структур. А функциональное — это когда программирование с использованием функций.
Короче опять чушь несете.
Я вам не хамлю. Я констатировал факт того, что вы забыли свои же недавние фразы.
Следуя оффициальной терминологии в C# именно что generics. Причем "Generic programming" != "Generics".
Прежде чем пороть чушь, пройдите по своей ссылке, и почитайте что в C# именно что generics, и что даже code generation является одним из подходов к Generic programming. И что type erasure не является необходимым атрибутом generic'ов. И вот дабы это наглядно показать, вам привели в пример C#. На что в ответ пошла чушь навроде "В C# те же шаблоны". Глупо и некрасиво.
или
Проблемы с памятью?
Можно долго спорить над терминологией, но прям офф доки говорят что это дженерики. Но вы, конечно же, а как иначе, умнее этих недотеп из МС…
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/differences-between-cpp-templates-and-csharp-generics
type erasure запили как компромисс, который позволили по минимум переделывать виртуалку, коих для джавы мнооого. А еще сделать весь старый код совместимым с новой джавой.
Наличие type erasure в обной из реализаций дженериков не означает что оно есть везде.
Ну и как, например, "по хорошему" обойтись без кастов из
interface{}
при использовании, скажем, модуля heap? Научите плз.Это вы щас историю успеха Go описали?
Не переживайте, наговнокодить можно и сейчас, было бы желание. Врядли ситация кардинально поменяется.
Это не волнует фанатиков и дураков. Так то народ постоянно стонет и ругается на обработку ошибок в Го (точнее на ее отсутствие). Блин, этож самая популярная тема похейтить сей яызк :D
Ну во-первых, тут три строки. Там три строки… Потихоньку набегает. А во-вторых — а зачем так привязываться к
filter
? Ведь можно поговорить о более удачных примерах из оригинального пропозалаТам приводят
Неужели ни разу не понадобилась фунция
Keys
?А, понял. Проекты просто махонькие. Ну тогда норм.
Ну это если функция фильтрует слайсы, то она
"бесполезная". Ну гляньте на примеры из статьи https://blog.golang.org/pipelines, например функцию
merge
. Как же весло, когда нельзя такую функцию добавить в непонятный пакет, а нужно копипастить по большому проекту!Мне кажется ваша логика сломалась: с дженериками будет копипаста из-за того, что люди забудут об существующей реализации — это плохо, но без дженериков будет еще больше копипасты — это типо хорошо.
Ну добавите вы проверку. Сделали такую проверку в рантайме, тип не тот, паники нету… Но что дальше? Напечатать в лог "Unsupported!!" и продолжаете выполнение? Т.е. в вашем понимании это "все работает"?