169 похожих чатов

Class Bird { fly () { } } class WaterFowl

extends Bird {
swim () {}
}

class Duck extends WaterFowl {}
class MallardDuck extends Duck {}
class MottledDuck extends Duck {}
class BlackDuck extends Duck {}
class PekinDuck extends Duck {}

class Swan extends WaterFowl {}
// ...

class Goose extends WaterFowl {}
// ...

class GameFowl extends Bird {}

class Pheasant extends GameFowl {}
class Quail extends GameFowl {}
class Partridge extends GameFowl {}
Your system is amazing, all of your pieces fit together perfectly, and all of your classes are super-tiny, because they’re all inheriting the functionality they should be, all the way up the tree.

6 months in, your manager asks you for two new birds:
Emu
Cormorants

What now?
Keeping in mind that practically all Cormorants fly, and feed by diving.
…practically all…

One sub-species of Cormorants, Flightless Cormorants can not fly (as the name might suggest).

You already have a taxonomy of hundreds of classes, in an intricately laid out system.

And your type-system in your code is working perfectly. Just by genus, or by family, or what have you, all of the branching subclasses of that root class (itself a branch of some other thing) can pass right through…

…now what’s going to happen to your taxonomy… the topology of your tree…
…how easy it will be to trust that once your tree gets shuffled and lopsided, that things flow through all of your typed method calls as easily as before? Will you eventually find yourself having to write methods like

public Boolean checkCollision (Bird a, Bird b) { /* ... */ }
What kind of bird? It might be really easy to check if one is flying and the other can’t fly… …but that requires crazy overrides, and basically everything can flow through because you’re just checking “Is it an Object?” in order to accomplish things in your type system, now.

This is frequently how game engines end up.
Everything is an instance of some descendant of GameObject so that worst case, your data can still be passed around.

So if this is the BAD way to look at things, what’s the better way?
Traits (Mix-Ins).

Languages like C++, Go, Scala (and of course, JS) allow you to define multiple sets of functionality to extend onto yourself.

What if, instead of this hierarchy, you had multiple objects with methods that you borrowed, instead?

// not valid JS
trait Flyer {
fly () { }
}

trait Swimmer {
swim () { }
}

class Bird {}

class Duck extends Bird, Swimmer, Flyer { }
class Penguin extends Bird, Swimmer { }
class Emu extends Bird { }

class GoldenRetriever extends Dog, Swimmer { }
Now it all takes care of itself.

We are composing our objects, rather than inheriting deeply.
Our type system now cares about things which we say our object can do, not what we say our object’s ancestry is.
If I had every skill of all of my ancestors, I’d be unstoppable.
More to the point, now my kid and I can have different strengths and weaknesses, and its okay.

When Crockford gives talks these days, talking about “Parasitic Inheritance” or something of the sort, he’s really talking about mix-ins/traits (without any keyword support for them in JS, unlike classes).
FunFunFunction’s mpjme has a great solution to my Duck+Penguin problem, or what he refers to as a MurderRobotDog.

I hope this helps you understand why people are wary around “class”.
It’s not that it can’t be used well, and can’t be used responsibly…
…it’s just that the vast majority won’t, and then they’ll complain about it, when their stuff breaks.

2 ответов

4 просмотра

The last part there, about traits

Dude put this on theDevs blog

Похожие вопросы

Обсуждают сегодня

А как старый хаскел с новым стыковать ? потому как тут работает https://play.haskell.org/saved/C3xpMzcd, а вот тут https://stepik.org/lesson/7602/step/9?unit=1473 нет ошибка C...
Fedor
131
Вопрос я правильно понимаю что в коде newtype ArrowMap k v = ArrowMap { getArrowMap :: k -> Maybe v } getArrowMap есть функция типа k -> Maybe v, если да, то не понимаю задач...
Fedor
61
Продолжая диалог про свифт в проде – сейчас возник вопрос в активном наборе бекендеров. В основном в нашей компании мы фанаты Java Spring и полностью ей довольны. Однако найм ...
Guseyn
27
Как Вы считаете нормально ли в двадцатых годах 21 века в ВУЗах Российской Федерации обучать студентов работе с TASM? Не слишком ли это "архаично"? (Если оффтоп или флейм для э...
Spiker01
52
Комрады, хотел уточнить. Проперть в OnDestroy юнита-хозяина по-прежнему доступна? И еще уточнение: finalization юнита наступает раньше или позже OnDestroy?
Ed Doc
48
Читаю сейчас [нет, уже больше не читаю!] курсовую о Булгакове, написанную, похоже, с помощью ChatGPT. Это удивительный психоделический опыт. Текст в основном написан в стиле б...
✨ Uni [🌊 В отпуске]
1
Всем привет! поделитесь, пож-та, как кто дебажил / решал проблему с 504 Time out ошибкой от nginx, когда стучишься на свой vapor сервер? в логах /var/log/nginx/error.log е...
Paul
24
Привет всем. Не знаю, удачный ли чатик я выбрал для вопроса, но он как будто в целом про концепцию фп и конкретно про Haskell. Прочитал, что в целом в мире фп нет идеи мутабел...
Gellert Cringewald
15
Как добавить ссылку в Быстрый доступ в Проводнике windows 10? Нашёл, как на power shell сделать, но может есть способ через Дельфи?
А
31
@helgispbru @Dreamer_0x01 @Pathologic93 @webber_12 Не уверен, что вам всем это жутко интересно, но в продолжение недавнего диалога отправлю свои наброски. Хочу понять, правил...
Андрей [aharito] Харитонов
13
Карта сайта