Rust Programming - No Inheritance
Вставка
- Опубліковано 2 жов 2024
- See the full video at ➜➜ • How does Rust make me ...
Help support this channel: / jeremychone
Rust Programming has no inheritance, but it is for the better. Checkout the full Top 5 Reasons How Rust Programming make us write good code: • How does Rust make me ...
Jeremy Chone:
Twitter - / jeremychone
Discord On Rust - / discord
AWESOME-APP - awesomeapp.dev - Rust Templates for building awesome applications.
Patreon - / jeremychone - Any help is a big help (for Rust educational content)
Other popular Rust Programming videos:
AWESOME-APP Full Overview - Rust template for building Awesome Desktop Application: • Building Awesome Deskt...
Tauri Quick Introduction (Desktop App wit Rust Programming): • Rust Tauri 1.0 - Quick...
Rust Web App tutorials series: • Rust Web App - 1/3 - D...
Rust Bevy Full Tutorial - Game Development with Rust: • Rust Bevy Full Tutoria...
Rust for Java Developers series: • Rust for Java Develope...
Playlists:
Rust For Desktop App: • JC - Rust Programming ...
Everything Rust Programming - Tutorials, Courses, Tips, Examples: • JC - Rust - Everything...
Rust Programming for Web Development: • JC - Rust Programming ...
Rust Courses: • Rust Course 2021 by th...
Furst for Java Developers: • Rust for Java Developers
OOP: everything is a class
Rust: everything is an algebraic data type
everything is an *object
Oop is better 😢
@@UNNIETKTJOop sucks aas
@@UNNIETKTJ oop is dogshit
@@UNNIETKTJScala can do both
Cold shower everyone needs: There's nothing new after the Lisp.
I guess someone needs to do something about it
Well, counting parentheses ain't no fun, y'all!
yeah I've been able to program emacs and gimp so hard with Lisp, so that makes it a general purpose language
@@forgetfulfunctor1
You're a hero, and your contributions to the world will not be forgotten!
IOW: Actually doing anything with lisp is so cumbersome that lispers are constantly impressed and shocked that Turing-completeness is a thing.
My life long dream of typing Floor(Floor) is finally possible 😎, Poggers
Yo bleach is back bro, i can die now
Ah yes, the floor is made out of floor
@@Rudxainabsolutely beautiful 😂
you'd need a box tho
@@jo_kil9753It's not a Floor struct containing a Floor struct. It's a Floor variant (for some enum) containing a Floor struct. They're separate things, so it's not a recursive definition.
You can simply make a trait and implement it to the enum instead of each struct
but you cant specify different implementation for a trait on basic enums, they have to be structs
You can also implement the trait for the structs themselves
You can also implement common behavior on the `enum` type itself using a `match` statement to provide specific responses.
That's what I like. Rust implement algebraic data types instead of class for his construction
Is it possible to define a trait which is implemented differently for each enum variant but call the different implementations on the enum variant?
@@boopumer You'd use the same approach of pattern matching on the enum variants.
that reminds me of type classes in Haskell
traits are basically type classes. There is a set of types that implement the trait, and generic functions can be written to accept any type implementing trait Noise, and then it can use anything from that trait.
Typeclasses, traits, interfaces, protocols etc are all the same
Rust’s type system is basically Haskell’s with added lifetime analysis, but without higher kinded types (meaning we can’t (easily) write traits for functors and monads).
@@vikingthedudeNot entirely. If you have two `Cat`s in languages like C# or Java, then they both could have different implementations of `Noise` because they might be arbitrary subclasses of `Cat`. That's one of the reasons why implementing binary operations in these cases is a bit weird and wonky - you get all the ` IComparable` weirdness which breaks once you start adding subtypes to it.
However, C# now has static functions in interfaces, which do actually work more like type classes in Haskell and traits in Rust.
The difference is that Java-style interfaces associate the implementation of the interface with an instance - each instance can have a different implementation.
However, type classes/traits associate the implementation with a statically determined type, which is entirely different.
One common misconception is that OO needs to be embedded in the language. You can model your entities with classes and implement without it. We just got used to have the full set
you can also invent GObject in c and then get disgusted and throw up that nobody not even the compiler helps you if you did something wrong. guess the vala language is the sulution for gui programming in gtk if you want a compiled language.
I added OOP to my Forth compiler by simply creating a set of preprocessor macros (2K source). I did *all* design patterns (and more) to prove it is the real thing. Actually, C++ started its life as a C preprocessor - and there are still plenty of examples on the web how to add OOP to C.
Basically, a class is nothing but a struct with function pointers - which are initialized at instantiation.
@@Henry-sv3wv In Forth, you have to balance a stack. Every conditional or loop opens up a unique possibility to create a bug. It breeds discipline.
@@HansBezemer in fact current Cpp implementation is not much different than that
@@motbus3 What the heck are you talking about? C++ compilers haven’t been C frontends for 25 years.
Interestingly, this is similar to some of the ideas I put forward in my PhD dissertation in 2010.
ok
Link the arXiv? 😀
Inheritance, the shit we are forced to keep from our ancestors
Gold hahaha
As much as ignorance, I guess
yes
Then if its riches you should also be rejected them shit 😂
Generational trauma for sure
The problem I see most people coming from OO languages have with Rust is trying to shoehorn patterns intended to solve shortcomings of OOP, especially aspects of data modeling, and come to the conclusion that Rust isn't suited for such tasks. Rust is plenty powerful and easy to work with once you stop thinking in classes. Traits are not interfaces.
What do you mean traits arent interfaces?
but traits are interfaces? no?
They work just like an interface does, it is a contract between the implementor and the interface that should be implemented, i don't get why it isnt an interface lel
From the Rust Book.
Note: Traits are similar to a feature often called interfaces in other languages, although with some differences.
You are a parroting phony.
don't really need an enum. could use a marker trait or use the trait itself
Calm down im just starting learning this lol
Is there any way to force all structs in the enum to have a trait implemented?
So that if it gets removed from any of the structs, I can get a compile error.
If you remove a trait and the trait was being used, you will get an error anyway. If it wasn't being used, then no harm done.
If you want something "more polymorphic", it would be "impl MyTrait" or "dyn MyTrait". That guarantees the type in question will implement the trait.
You can implement a trait on the enum, which you will likely do by matching on its variants and forwarding to a trait implementation on the inner type. This will obviously result in a compile error if one of the variants doesn't implement it.
I like the idea of implementing Deref on an enum, with the target being the trait each variant should be implementing. If you need an example, remind me and I'll go find or recreate it.
I mean, there's a reason why most game engines and most AAA games make heavy use of inheritance and are written in C++. It allows for much easier code, especially if you have multiple types of something and want to write a more generic function that uses a parent.
i.e, something like Grand Theft Auto makes heavy use of inheritance. For example, it could have a CVehicle class thats extended by CAutomobile, CHeli, CPlane, etc. Now, it could just tell a CPed to get into a CVehicle and it'll work on any vehicle type just like that. You end up with an expandable system that can accommodate any new vehicle type with ease. OOP is a good tool, and just like most good tools can be misused, but powerful if used properly.
Not just games, most frameworks, platform SDKs like Android and iOS, game engines etc. use inheritance extensively and excel at it because the people who make them know what they're doing, unlike people who discredit features like inheritance because their favorite language doesn't implement it.
Uhm. I like C++ as much as anyone. But if I'm correct, a lot of modern engines (a lot not all) make use of ECS, a more data-oriented paradigm with minimal inheritance.
Inherence is defiled and bad feature that leads to mistakes and bugs. Too bad it was popularized. The thing you are describing is polimorphism and it is one of the most important concept in programming. Rust archives goals of Inherence in modern and more flexible ways that are friendly for performance and developers. It decouples behavior (traits) and data (composing & DeRef)
Only reason they are written in C++ and adhere principles of C++ is because there were no performant alternative for so long, they had their tooling just for that.
Also, what you say can be achieved with traits in Rust. You don't have to inherit a whole class implementation to do polymorphism or monomorphoism.
@@Lord2225 I just dont see why you wouldn't want to inherit the structure in its entirety in a proper polymorphic setup. After all, you want them to share functions, and those functions usually also depend on properties on the class itself. Also makes the final assembly much smaller as it doesnt have to repeat code just to get the same value, but to be fair there is templating that will repeat sometimes. Then again, who cares about assembly size, you're using rust.
This approach breaks the Open-Closed principle. Although it can be achieved with dyn trait, it’s a very verbose, impractical, and developer unfriendly way to achieve it
This is, for me, one of the biggest disadvantages of Rust
Open-closed is such a vague concept, if I had to guess you are trying to shoehorn OO design patterns into a non-OO language.
rust has to be verbose for the compiler to ensure the safety of your program. THAT is the main advantage of rust and the verbosity is a price I happily like to pay for that purpose
@@woobilicious. any language with structured data and interfaces is OO, deal with it.
So, it doesn't break. Rust causes later implementations to occur at the trace level and this won't literally violate the principle, but I think you're using it in a place where it doesn't belong.
@@Tibor0991 That is a very liberal interpretation of what is OO. Data structures and interfaces are the basis of every language not at the assembly level.
I thought the "Rust lacks X, therefore X is inherently bad" thing was just a meme
No, but “X is inherently bad, therefore Rust does not have X” is one.
@@JeremyChone Except inheritence isn't inherently bad. It is bad, like most things, when used incorrectly.
@@JeremyChone Inheritance is inherently bad?
@@tiredcaffeineIt kind of is bad tho. Inheritance always has the diamond inheritance problem where you have undefined behavior from ambiguous inheritance. You also have to implement all methods even if they don't make sense. Using a trait or interface limited inheritance model allows you not only to have stricter control over what a type is inheriting compared to an object, you also are able to stucture the underlying data into an Entity Component System which allows for better memory access compared to an Object Oriented model.
@@gljames24 Again, that's inheritence used wrong. If you inherit from two different classes that inherit from the same base class, then that's on you. If you choose a wrong base class to inherit from, then that's also on you. Read Circle-Ellipse problem.
If you use inheritance correctly, it can be a really powerful tool. If you use it wrong, it will cause you headaches.
i dont know about other, but i really like to call this programming paradigm of semi OOP with trait but no inheritance as Polymorphic Programming.
i'm loving Rust reading the rust book
The one thing I wish Rust had is Go's syntax sugar for struct composition.
I wonder if you can do that with macros hm
I always use composition anyway. Not all cats are pets; they may or may not have a pet component. Inheritance is almost never useful in practice.
Want more videos like this shorts ❤
that looks simple and easier to implement polymorphism.
Needing an enum that passes in the type then essentially making an interface is easier than an interface?
OO is worse than goto. At least we admit goto is dangerous.
Mmm switching by typeid with match instead of static methods through templates
That rust genius coders
This is faith healing. Only this time, the malady too requires faith.
Inheritance means you can define an "Animal" struct and all animals(including pets) inherit eat, sleep and reproduce methods.
I think the problem is how much people simply use inheritance _wrongly_ , or where it isn't useful, rather than inheritance itself being a bad thing.
@@mvnkycheez The problem that most people have with inheritance isn't inheritance itself but what they first think of when they hear it: dozens of layers of abstractions and factory classes in the style of "modern" Java. But inheritance can be really elegant - if used correctly.
And you can define an "Animal" Trait with default implementations for eat, sleep, and reproduce.
so again it boils down to being a skill issue and instead of admitting that people bash OOP
Go also doesn’t have inheritance, classes ..etc so was a nice experience to program with
I almost vomited looking at that syntax
Physics over cosmetics.
I’m just glad that people are finally realizing the value of functions and composition.
Thanks for the video Jeremy.
yes so happy people are realizing oop is just a bunch of hot marketing air
@@MCRuCr I prefer composition, but I like composition with oop, not functions.
I think there should be a way to auto implement a trait for the whole enum when all containing types implement the trait. Bsp:
Dog, duck, and cat implement noise. Then there should be a way to simply 1 line implement the trait for animal instead of needing a match that forwards the method to the individual versions.
Often when you think "there should be some way to do x", there's a crate that gives you macros to do it.
I looked it up and found enum_dispatch, which seems to do just that. One line on the trait and one line on the enum.
Or make them implement a pet trait
Actually, it makes more sense to have a Cat or Dog have a reference to a Pet. Just sayin'.
Yes, there are many ways to skin the cat. You could have Pet with .kind attribute which would be an enumeration with Cat, Dog, Snake, … variants.
So a van has a car base and honk trait like the car as well.
How would you solve this problem: Imagine you have a sherd base class like a car, that has its position, velocity and acceleration. Now what you want to do is create inherited classes that all act differently by doing different things but still with a common interface. The point is that the base class may have lots of fields, and copying them for every subclass is error prone and can be buggy.
From what i can tell rust excels at doing similar things on different data (imagine the classic shape polymorphism example), but kinda lacks at doing different thing with the same data (with a common interface for abstracting such operations).
Define a struct to hold your common data attributes, create types or an enum that holds an instance of that struct, define a trait to define the common interface, and implement that trait on each type.
You'd either define traits that have default behaviour and polymorphic functions which use these traits. You then implement the traits for all the types you think need to be able to do these things
This is the only reason I haven't switched to Rust for most of my code; fields just aren't flexible in Rust. Some people see this as a good thing, and in some contexts it is, but in the contexts I find myself in, it is overly restrictive and leads to _less_ clean code.
What people don't seem to understand is that it's not that Rust _can't_ do things like this, it's that it's not well suited for them.
@@mathgeniuszach As Jake and Niko have said: make a base struct with all the common fields and a trait for the behaviors, then make specialized structs with the base struct as one of its fields and implement the common trait as needed. Alternatively make an enum instead of (or in combination with via Deref) a trait and pattern match on each variant to get different behavior. The enum can be more efficient, but less flexible.
@@chinoto1 Literal quote: "What people don't seem to understand is that it's not that Rust can't do things like this, it's that it's not well suited for them."
Macros ease the pain a bit (e.g., #derive), but it's just not clean otherwise.
make a video for python codes interested to learn Rust .... simple steps with basic projects.... so they can continue
Yes, this is on my todo list. Python to Rust, and JavaScript/TypeScript to Rust.
Why is this a cold shower we “all need to take”? What is this rebellion agains OOP? I only hear subjective arguments from Rust enthousiast. The best being that ‘it is often used wrong’. By that sense, any programming paradigm is a bad idea.
To summarize the linked article: inheritance causes subclasses to break when super classes change.
@@Lestibournes Rust code will break just as easy, when depending code changes. What is the point?
@@travelan the point of the article is that using encapsulation + interfaces instead of inheritance can prevent many cases of breakage while still achieving the same desired result.
@@Lestibournes 👍
Typical Rustacean ignorance, they think Rust is not OOP just because it has "flat" inheritance (i. e. an object can only inherit one or more interfaces, but can't inherit further), but flat inheritance is the de facto standard in modern C++.
Is this comparable to discriminated unions, except using an enum instead of a parent union type?
Yes, with sum types. Enums are often referred to as Algebraic Data Types (ADT).
It's very nice, I remember in some of my old game projects I would have several levels of inheritance, and hurts my eyes to look at that now.
Then I started using interfaces more it was just more dynamic and allowed for better generic code.
I feel like this works very similar to that, but more modular and just cleaner.
Same here. When we moved our backend from Java to TypeScript, we refactored to use many more interfaces than classes, and the code became more manageable.
We still use some inheritance in TS, but very light.
At first, Rust's hardline on no "data inheritance" was missing, but eventually, when using traits, generics, enums, and macros, those considerations do not come up anymore. Instead, the code becomes much more data-first focused, which is better for runtime purposes, as 80% to 90% of the code is statically bound (v.s. defaulting to dynamic dispatch), and interestingly, our code design improved as well. Win-Win!
@@JeremyChonesure your program started faster but I highly doubt your TS is running at the same efficiency as your Java code, if it is, your Java was horrible.
@@JeremyChoneI think you should rebuilt it in rust.
@@pickledeveloper Ok, a few points:
- "Rebuild in Rust" - It isn't about rebuilding existing projects, but utilizing Rust for the backend of our new projects. I'm even creating a video series and a dedicated website, [rust10x.com](rust10x.com), to share the production coding blueprints we are using.
- "Java vs Node.js speed" - Being in the development field since the late '90s, we've traditionally viewed JavaScript more critically compared to Java, and for many good reasons. However, the period from mid-2010 to 2020 saw a significant shift, especially with the advent of Node.js and Google endorsing Node.js as a first-class citizen runtime. Although the V8 engine is technically slower than Java's JVM, the essentially async/NIO-based ecosystem leveled the playing field between the two, particularly for web app scenarios.
To illustrate, when an app in a Node.js environment requires data from S3 and a database, the S3 command can be executed asynchronously. This was somewhat cumbersome to achieve with Java in the past. Therefore, while Java had the edge in raw speed, the overall performance became somewhat comparable when considering all aspects, including the easier integration of Node.js with docker/kubernetes environments. This shifted the focus towards developer productivity, where we found Node.js, coupled with TypeScript, to offer a more favorable environment.
Now, all that being said, as mentioned initially, we are steering all our future development towards Rust, drawing from a decade of experience in production coding. You can find insights and guidelines on this transition at [rust10x.com](rust10x.com) and through my video channel.
Thank you for the engaging discussion and your insightful points. Looking forward to more. Happy coding until the next time!
I suppose this is a win for the ontologically challenged.
Rust had potential but then it had to be “unique “ what is all this mess just handle it like cpp does bruh
And that's how it should be, I love rust because like me we both think that evloution is a scam
😮
PHP was right 🎉
Good one. But didn't they add a class now?
In this example, if we would like to have a new pet called Bird, wouldn't we have to modify the enum Pet to add the new Bird(Bird) variant??
Instead, why don't we have a trait called Pet and move the `noise` function into this trait? And we no longer need the Noise trait. Then in order to have the new pet Bird, we would just create a new struct called Bird and impl Pet for Bird... and we would not be changing anything that already exists. The solution with enum Pet to me is not extensible because we would have to modify it for each pet we add in the future.
You could definitely make a `Pet` or `PetBehavior` trait, and then rely on trait objects and dynamic dispatch, which is also a valid approach.
Both ways are, in fact, complementary, as you can still have your `Pet` enum that would implement `PetBehavior`, and then you get the static dispatch as well.
So, you can have it both ways.
While you could do this, its important to know the performance tradeoffs. By using an enum, the compiler can know at compile time the maximum/minimum size of the returning type, and can use stack memory to do so. By implementing this using a trait, we may lose this compile time behavior, and thus the compiler may end up using a runtime based alternative (especially if you use a return type like `Box`), that will use heap memory.
Its a tradeoff between performance and extensibility, but it may end up only mattering if you do this hundreds to millions of times during execution
How long until we get Rust++ with inheritance?
Inherence is great ... when you use it for what its supposed to be used for ... which is not code reuse.
i.e. if composition/ the strategy pattern solves the problem you are facing with inherence you are doing inheritance wrong.
Inheritance is for establishing known and immutable type hierarchies. Nothing else. If you really need to force yourself to not be bad at programming a lot of languages allow you to establish those type relationships using interfaces/ protocols which explicitly dont allow for implementations.
Taking them out of the language completely is just admitting your are too dumb to be allowed off training wheels and you think that other people are as dumb and cant be trusted.
Its cute but no thanks, you have fun playing in the sand pit I will keep my language features.
This literally just helped me build my rust program successfully
You can use traits and make it easier
c++ -> std::variant and visitor pattern
Inheritance is useful. Ruling it out, seems like a whimsical decision. And it is made weird by the fact that Rust allows trait inheritance. Therefore it's effectively the same thing, except with traits (analogous to interface and virtual classes).
People love to hate
It's not the same thing at all. Haskell uses the word "derived" which is more explicit about what's happening. If a type wants to implement an interface, i.e, derive an interface it's possible only if all the sub components of that type already implement that interface.
Otherwise you'd have to prove that your type could implement that interface.
And these interfaces in Rust and Haskell could be used as higher level types in function arguments. I doubt this is similar to OOP inheritance.
@@samuraijosh1595 I'm not aware about Haskell.
@@SbF6H you don't have to be to understand my point haha
Isn't traits extending other traits inheritance?
Inheritance typically means you inherit the properties as well.
@@JeremyChone I see, that makes sense.
You can additionally use DeRef trait if you want all methods and fields from composed struct. It is handy if you want to build extension for other struct but still use it as before without outer.inner syntax.
Thx for overcomplicating simple things rust, ily ❤
what's simpler than an enum?
@@JohnnySacc i mean, enum is meant to enumerate something, I meant to make it complicated but not difficult.
When I learned Haskell, I realized functional classes was exactly what inheritance was trying to do but OOP made you do it badly.
I wish Go had Rust enums
Closer matching of program structure and algorithm structure simplifies programming. from a modeling problem and a program inheritance hierarchy, down to modeling a problem and appeasing the rust compiler.
The rust compiler does know best, so at a certain scale, the compiler complexity grows slower than the inheritance complexity. Therefore, rust abstractions are less complex- to a meaningful degree- at suitably sized and for appropriate types of programs. A conditional win for rust.
this is strateg pattern.
The enums I dont like, because if you have many classes that "inherit" another, you got to keep going back to this, and the Parent class has to know about all its children, but a parent shouldn't need to know about any of its children. That is really bad coupling.
I love Rust and I love traits. HOWEVER, I have found that in the realm of unit testing, mocking is a bit of a pain in Rust without inheritance. If you want to mock a struct and swap it out while running tests, good luck. Instead, you have to hide every single struct behind a trait which just adds a ton of "fluff" to your code. In this specific case, I reeeaallly wish Rust had inheritance as an option and just didn't recommend it otherwise.
If you want to replace struct, you must use a trait. The structs - is only about data, not OOP objects. If you have struct Person it is only Person, not null, or children.
@@vas_._sfer6157 yup, that's exactly what I'm saying. But because structs are not objects and can't be mocked, unit testing can be a pain in Rust.
@@leonidasiii2857 It is not a bug. It is feature. Struct is always a concrete types. If we need a mocking we must use traits.
If we have to moke network querry, we can use SomeStruct (N is empty struct that implement our Network trait with some methods). And now, we can mock a network (SomeStruct).
And generic it is not a problem we can use a 'use' keyword.
@@vas_._sfer6157 I'm aware that it's intended, and I'm aware of how to get around it 😂
What I'm saying, is that in this specific case, it's a pain and inheritance allows for cleaner more intuitive code than traits
You never need (using mock) to do this in practice, you just need to implement traits that you want to be as a dummy. Most of cases, you either go property tests or implement an instance of the traits, by this, it also promote granular way of designing behavior through trait systems.
Execute this
Num1 = n
Num2 = c
Num3 = i
Num4 = e
Print(Num1, Num3, Num2, Num4)
All in python
As a C# dev I miss inheritance. Most of the devs misuse it and then blame it. Composition is a way to organize data within classes while inheritance is a way to define classes ad-hoc.
as another C# dev, i agree
Coming from the similar works of Java, I disagree. The only thing that is more useful than harmful in either of those languages as far as oop goes is interfaces. Checking if a type satisfies some condition. Extending classes brings implicit functionality with it.
I can’t think of anything good that requires extending rather than implementing.
@@asdqwe4427 probably you had very bad examples
@@asdqwe4427 You work with Java, that’s why. It’s OO out the ass. That’s probably its biggest flaw. Like all good things, moderation is key.
You don't miss inheritence, you miss polymorphism - which Rust has decent primitives for. That said Rust doesn't operate in the same space as the likes of C# and Java, you're just not meant to push things to the runtime (even though you can) when writing Rust code. I would suggest you explore languages like Go, Julia, and Clojure. Go and Clojure demonstrate how not tying interfaces/protocols to inheritence hierarchies can achieve wonders and Julia and Clojure together show how multiple-dispatch solves all the problems inheritence does and more.
Traits
Not same
Thats just interfaces from java...
it's not! Traits can have default implementations. It's closer to abstract classes which can be inherited multiply + a mechanism to handle the diamond problem
Java interfaces can have default implementation as well.
This reminds me of Nathan Stocks’s description 🤔
It would be better for Pet to be a trait...
There are different ways to skin a cat.
Yet it is a pain in the ass for people that knew when to use one and other and used (in C++ ) protected inheritance to create automatic composition by template assignment.
You’ve just gave me another reason to invest my time into this lang 😅
guess they favour composition over inheritance, which isn't all too bad
Tsoding coding in rust is kinda... ironic.
well, they say rust accidentally fixed all the problems that every language has
Lol @cold shower 😂
As a former polymorphism fanatic, I've absolutely loved diving into Rust. Thankfully I'd broken my addiction a while ago, but Rusty took things in a beautiful new direction for me.
So in Rust we use product type and sum type, right
There's "behaviour inheritance", which is used for regular inheritance but in a controlled manner.
Theme?
Rust is the only language that is being forced down my throat.
Everyone is telling me to try it and it feels like it is cornering me
❄️
Feels like the same way Java marketed to deep dowm its roots to legacy companies & every tech stack that been forced by managers,because they felt so (like falling into scam 😅)
23.11.2022 01:34 am ist
Glad I am not the only one.
Same. Can't go one day without UA-cam peddling me Rust content.
Love Go for this.
OO developers discovering Typeclasses for the first time
traits
Thats not a big problem, I do dislike the cryptic names of Rust library types though. Or will any no-rust developer ever guess what Arc should be used for without reading the docs. And there are more examples to this.
Choose physics over cosmetics. Taste changes, physics don't.
@@JeremyChone In my opinion good names are essential and also do not fall into taste. Especially because you can not refer to Arc as a name but an acronym. Maybe this acronym is well known to some people outside Rust, at least to me it is not.
If you are non-rust dev you realy don't need to know what is Arc. Besides, try to code any script dyn type lang without reading docs😂😂😂
No inheritance!?
Haskell does it better with typeclasses. Much more elegant.
traits are type classes
Isn't that quite appalling doe? You literally have to maintain an Enum and manually make sure that every Pet has all the traits implemented... Even if inheritance is usually not the answer it can still be useful for some things...
Shh, the rustaceans haven't gotten that far yet, the compiler won't let them get past the memory allocation.
You can implement traits on enums, you just need to pattern match the different concrete types. Or you can use a general case match if multiple types perform the same behavior for a trait
You can use a macro from the enum_dispatch crate to generate the enum code in a single line. The enum will implement the trait by just delegating to the struct inside the variant. Good example of how macros make the whole language extensible.
This will still require you to implement the trait on every struct, making the enum act like an abstract class. I'm sure there are crates providing ways to concisely emulate more OOP features if you really want that and just look it up. It's moving away from idomatic Rust, but if you feel that "inheritance is still good for some things", someone agrees with you and has already made a solution.
@@voxelfusion9894 You literally can allocate memory just fine. You just wrap the operation in an unsafe block.
Sounds like it's you who hasn't gotten past even the basics of the language before you tried to clown on others.
That’s almost exactly c++ lmao barely a seperate language lmao
In rust, i somehow always tend to forget about enums, that you can use it like a variant and emulate inheritance with it
Rust enums are one of its best features
Go needs something like this so fucking bad
I do miss Enums in Go, but i believe Interfaces do a good job
We dont need mess like this in our beautiful go
Love it!
Finally, the Conservative's programming language.
in OOP, changing of class inheritance is a nightmare.
So it basically achieves the same thing, but with different syntax? I can see some good uses, but why no option to do traditional inheritance?
because giving multiple tools for the same purposes results in chaos and frameworks wont be able to work with each other. every language should have exactly one concept to address each of a programming languages requirements (like encapsulation, interfacing, composing data, ...)
Abstract classes? Anyone?
Why would you need abstract classes in this case?
@@sunpoke5317 Did I said in this case?
Protocols
Wow this was a really easy way for me to understand inheritance, thanks!
This is not inheritance, that's precisely the point of the short: using composition instead of inheritance.
How to mimic inheritance in Rust if you really want to for some reason:
Make a base struct, a trait, and impl the trait for the struct.
Now make a struct with one of its fields being the base struct and impl the trait, calling the base struct's impl where needed.
I haven't done this myself, so let me know what downsides you find with this.
You can get some basic inheritance characteristics at a high level with traits and "blanket implementation," but you won't get far (e.g., override, overwrite, ...).
However, I recommend not mimicking inheritance, embracing the Rust language, and going with composition using struct, enum, and traits. Also, there are many great language constructs and patterns using From/TryFrom, monomorphization, and macros. Once you get the hang of them, the code gets very componentized, relatively DRY, and fully optimized.
It took me a while to rewire my brain from traditional OOP, and while I still use it when coding TS/JS, I do not miss it anymore when coding Rust (which is most of my coding those days).
@@JeremyChone overwrites of methods are total bs to begin with. it defeats the purpose of inheritance
The downside is that you inplement every single method again!!
You can use Deref tho, but that's a bit abuse of the idea of deref.
@@Merthalophor Yeah, that could be a nuisance, even if it's just `fn foo(&self) {self.base.foo()}`. I haven't done much with extending classes or anything else involving inheritance.
Imo inheritance is generally a bad idea. Interfaces (Rust traits | Haskell typeclasses) together with ergonomic unions (Rust enums) result in much more reasonable code.
From what I can see, the only place inheritance (and object-oriented design) makes any sense is when you're simulating a bunch of distributed agents.
unfortunately most of my computer science course revolves about inheritance, because of things like encapsulation and separation of concerns. And if you work in a company you most likely are modeling your code (with UML but also) with inheritance.
I don't think I've ever seen a UML diagram used.
So rust doesn't have inheritance, and now inheritance is considered bad?
Enums can be used incorreclty too. And I've seen it happen more than inheritance.
Brian Will once said, Inheritance is BAD
Puso "," y luego cerró llaves, eso no es error?
Trailing comma is ok in Rust.
@@JeremyChone That could be bad programming practice
@@tilin7518 actually it's opposite.
I never really liked this explanation. Sure, in this specific case, you can use enums instead of a common interface, but it's not equivalent in general.
The entire point of interfaces is that they are *open*. You can always add new implementations later without changing code. This is absolutely not the case with enums.
Also, Rust has a great way of handling open "interfaces": Traits!
If you wanted something that was as least as powerful (more powerful actually!) as the OO solution for this, you could just have a Pet trait that specifies the Animals' shared behaviour and implement it for each one.
Traits are for behaviors not data (i.e. properties). In Rust, you cannot inherit properties.
@@JeremyChone You don't (well, shouldn't) abstract over data though. If you want to write a function that works on Pets, you are going to write something that is generic over the behavior of that Pet, not the data it stores.
If that behavior includes "get the name of the Pet", then you can still have a method for that, which just looks up the field.
Traits are great at this.
This is exactly why it's usually considered a best practice in OO to write getters/setters, so that class fields are not exposed.
Not sure, but if those patterns work for you, great. Happy coding!
By the way, I would agree that this Pet example was just an illustration to make it short and sweet.
Depending on where we want to go with this, we might want to start with an enum or a struct and treat the data variants down the structure.
With traditional OO languages, you can inherit data (i.e. Properties), behaviors (interfaces & class methods), and annotations (e.g., in Java).
In Rust, you do not have the "data inheritance," so you have to structure your data relationships differently with a combination of Struct/Enum. I think it is for the better, but it takes some brain rewiring.
Traits are for behavior componentization and should be used accordingly, but they are solving a different problem.
As of now, I think that by being "data first" Rust has picked the right angle to build an expressive language while being very close to the machine constraints, giving us back maximum performance and data integrity.
I want a framework written in Rust, for Python and Julia.
that kinda sucks
I don't think so. Composition. works well much of the time but inheritance is a beneficial feature. It is not something that always should be avoided.
Can we inherit a square from a rectangle?