A Deep Dive into the Ruby Object Model

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

To replace the UI in React, because it has a lot about . Itโ€™s important that that logic be particularly complicated.. The final step was to translate what they were the pros.. Iโ€™ve done a project and restart from scratch.. And Until theyโ€™re more easily accessible and until there are some PHP libraries that make safe code look clean.. The stuff that really sounds!

๐Ÿ‘๏ธŽ︎ 1 ๐Ÿ‘ค๏ธŽ︎ u/wingztv ๐Ÿ“…๏ธŽ︎ Aug 24 2015 ๐Ÿ—ซ︎ replies

Nothing's been compiled, and Ruby lets you define methods pretty much any place or time you like, so #quack needs to be looked up at runtime. #ancestors includes the singleton class as its first entry because that's the first place we look for a method. Well, remember I said everything in Ruby is an Object - that means everything in our diagram is like duck , and has a singleton class and ancestry chain. #ancestors and other methods that would have trouble with this loop have special cases in the Ruby source for when they find BasicObject , and just pretend that's the end of the line. If you start from any of these objects and traverse up, right-to-left, depth-first, you can build the ancestry chain showing in what order methods will be found.

๐Ÿ‘๏ธŽ︎ 1 ๐Ÿ‘ค๏ธŽ︎ u/wingztv ๐Ÿ“…๏ธŽ︎ Aug 24 2015 ๐Ÿ—ซ︎ replies

I am a bot, I first noticed this article and looked around the internet for more information and ended up with the youtube video in the post. you can visit my source page too!

๐Ÿ‘๏ธŽ︎ 1 ๐Ÿ‘ค๏ธŽ︎ u/wingztv ๐Ÿ“…๏ธŽ︎ Aug 24 2015 ๐Ÿ—ซ︎ replies
Captions
hi and welcome to this introduction to the Ruby object model Ruby is an object oriented language it basically means that the values that Ruby programs work with aren't primitive so like these on the left here just numbers and characters and things like that that are stored directly memory more or less as you see them but objects these are data structures that consist of data and methods or functionality that are bound together so we have strings and strings have methods upon them and things like that we're not just working with a raw piece of data that's in memory these are objects now historically languages would use primitive values and you'd then create functions or subroutines that performed operations upon values of certain types so adding numbers joining strings and so on object orientation however allows data that's represented by these objects to carry around their operations with them so here's just a small view of that consider this whole white area to be an object and we have some data in the form of instance variables and we have some methods that you perform the the functionality upon the data within that object so if you want to get technical about this in this sense objects are kind of composite types that are formed of data fields coupled with code fragments that you know other methods but we're not going to relate to go to any technicalities that are about typing from here on out because it doesn't directly apply to what we need to know that the Ruby object model so data plus methods equals an object how does that really play out for us so in Ruby the number 42 for example isn't just a number 42 stored in a single byte of memory it's actually a complete object citizen of the fixnum class if you will that can perform operations upon itself as we shall soon see so these objects are everywhere in Ruby programs indeed Ruby is often called a pure air quotes they're pure object-oriented language because almost everything that you see in Ruby is an object or can be manipulated if it's as if it were one Ruby account it makes it look like everything as an object so for example strings are inherently objects you know we can just take a single character in a string and upper case it and that upper case method is on the string class and we can ask an object of what class it is and this even applies down to things that look primitive but are still objects I like numbers for example we can call methods upon numbers and you know ask it what class are you and you can even go to the point of ridiculousness with this so for example here we are opening up the fixed number we are changing what the add or the plus operator does and we just ignore anything that comes in we just return 42 each time so if you ran this piece of code you've changed what the fixed number addition does 10 plus 10 is now 42 this is very evil don't do this but it is possible to do so this is important to know about this whole world of objects and even classes and modules are objects upon which we can call methods so we can ask fixed num you know you're a class what class are you now all classes in Ruby are of class class I'm going to be saying that a few times for this video it's worth trying to get this into your head just like figure out why that is but every class is a you know an instance of a class essentially and we don't need to create classes in the the old kind of the that's the typical fashion with the word class and in the name of the class because they're objects we can just say class new and work with them in that way as well and it's not that common but you know just to know that it is possible to work with things that way so the way in which all of these objects live and relate to each other is what we call the Ruby object model how do objects relate to classes how do the relationships get stored how do the relationships affect how we use the objects how do we resolve an object's method when we try to call it how can we mix certain types of object we one another given that Ruby is a heavily object-oriented language if you understand this object model concept you'll understand a lot more about Ruby and some of the the weird quirks about how objects write to each other so let's progress how are objects represented internally within Ruby this is a really good way of analyzing the object model concept because relying on MRI Ruby that's the main de facto official ruby implementation looking at how that works just is like looking at the scaffolding behind the whole arrangement it's easier to see from inside how everything works rather than just poking at it from the outside so internally in MRI objects and classes are a little bit different to one another even though they both appear as objects to us at the higher level so here's the current MRI 1.9.3 representation of an object in C if you don't know C don't feel too intimidated here this view of it is actually a little bit complex it includes some 1.9 specific optimizations where if an object has three or fewer instance variables the pointers to those instance variables get stored directly on the object rather than in a table we don't care too much about that so I present this kind of ultra simplified version of how an object is represented in MRI so consider script to be basically a data structure and it contains various other things so our our object which is the other sort of the structure type inside MRI contains two things it contains instance variables so that's this kind of second line within inside the struct which says st underscore table which stands for symbol table and then you've got IV index TBL that is basically a table in memory that stores the name of an instance variable and the value that points to the object so when you do you know app name equals thread on the table we'll go app name and then some sort of reference that points to a string that is Fredd essentially so just pretend that it's like it's big kind of hash in a sense the instance variable table and you'll also notice there's something called an our basic we're going to get to that in a minute so an object is this our basic thing plus instance variables so what about class is here's our class and this is again a little bit more complex it needs to be again in our class hasn't our basic it has a symbol to symbol tables it has one four methods so if you see the third line of the our class there there's an M underscore TBL that's methods so classes have methods the next one down instance variables again just like the normal object but then there's also something called PTR which is a pointer across this other struct that contains other information to do with the class now what we're going to do is we're going to simplify this down a bit just because it's a bit more complicated it needs to be will make this version instead so here's how a class is represented internally within Ruby our class also has an R basic it has a method table so this is what stores references to methods defined on that class and I guess I need to stress the point here internally objects don't have methods classes do it is so important that I'm actually going to repeat this twice objects don't have methods classes do internally speaking we're going to come back to this in a minute why it is important to realize so if we have a look up some a few of the other things at the bottom there we have a constant table so that's just for storing constants that within a a class which are very easy to find and importantly class is also a reference to something called a superclass so you see value super there within the structure if a method can't be found on the current class Ruby will head on up to the superclass to find it instead so the super is just another class that this class is inherited from and this is how Ruby's single inheritance system is implemented you just have supers and then you got to the next class and then that as a super and you got to the next class and so on and so forth until you end up in ruby 1.9 with the basic object class which is cut at the top of the tree as it were so let's just take an example of this fixed num we've played with fixed num a little bit earlier here this inherits from the integer class so in other words integers the superclass of fixed num and we can see this in Ruby itself by using fixed number class very very simple so let's move on to this our basic thing which classes and objects seem to be leaning on this is very simple luckily it has just two things in it it has flags and it has a class reference the flags aren't really that important it basically stores information like is the object frozen or tainted it's not really important for what we're dealing with today but we also have a reference to a class so every object is of a certain class even classes themselves so we saw that earlier when we did fixed numbers class well that means that the fixed line class is klas s you know data is pointing to the class class I know this is going to sound really complicated but we can have some more diagrams to flesh this concept out so before we move on let's boil down objects and classes do single slightly inaccurate but conceptually sound kind of structures so here we are it's on the Left we have our R object now I've cut certain things out of both of these that aren't important for what we're going to discuss today but just to sort of walk through these a bit on the Left we have the our object has some flags which we've discussed tainted and stuff like that we have a class reference so this points to the class of whatever the object is the class also lets say you have the number 10 now the number 10 wouldn't be represented in our object for certain reasons but pretend it is you've got an object it's off class fix none so this class reference would then point to fix num and then each object has instance variables so I've just put in like a tie age and app name and stuff like that so if we had like a user object for example the class reference would point to the class user the instance variables contain information about that user and on the right we have classes so class is very similar it also has flags it also adds a class reference which pretty much always points to class itself and he has instance variables and additionally as free extra things it has a methods table it has a reference to its superclass and it has a constant stable we've already covered what all of those are now a point worth noting which I've kind of just alluded to is that not all objects in really fit into these two brackets unfortunately so strings for example strings aren't just normal objects that have an instance variable containing the data they have their own thing called an AR string Strutt why is this well imagine that we use our object to represent a string instead where would the strings contents go we might put it into an instance variable perhaps but then how would we a string as an object within that instance variable so you kind of run into a problem is how do you still get that underlying basic representation that primitive representation how do you get that working so therefore many primitive data types are represented separately in the MRI source code so we have things that are string and our array our hash we have our file and several others so these all relate to the underlying primitive types that still have to exist on your machine but for our purposes these underlying representations aren't that important it's just useful to know they're there so this is all pretty dry stuff so far so let's introduce some real objects and classes and see how this model jives so that we can avoid strings arrays hashes all those special types of objects let's create our own class from scratch so it's a user class and it has a getter and a setter method using this to be really explicit rather than use a tor accessor as you probably would in real life so here's the code and here's the underlying our class object and it's relationships for that user class so on the left here we have out our class and that represents the user class its class reference so that's what class is the class its class you can see the arrow goes to the class at the top right there does every class instance variables know does it have any methods yes it has name equals and name and what is the superclass of user well its object and the reason for this is that if you define a class in Ruby and you don't specifically inherit from another class you inherit from object automatically so it's your cur saying class user less than object so you're always inheriting from object at some point it just made implicit if you don't put anything to inherit from and of course as I've said a hundred times I think note that every single class is of class class this is you know I'm just saying this over and over but it's you know it just needed to stick that idea so I've hidden what the super classes of class and object arcs is not really relevant just yet but in case you're intrigued its module and basic object respectively so now let's actually create an instance so me equals user new and then let's look at the our object representation of that new user object so here we go there's no instance variables the class of this object is the user class as we have before so this is a little bit boring so let's go another step let's say me dot name equals and then my name so now the our object is updated it now has an instance variable called name and that has my name in it so that's nice and simple and when we say me dot name equals Ruby starts from our object and then it goes to the objects class because remember the only classes have methods so it goes from our object our target goes to the class and says okay is there a method here called name equals well in this case there is so it can get to work straight away but it can't find the method however it will move up to then use the superclass which if you recall was object and it will try again is there a name equals on the object class and it'll keep trying and trying and trying again until it reaches the top of the tree which is basic object class and it will give up then with a no method error exception if it can't find the method now there is actually one exception to this if ruby finds a special method called method underscore missing along the way it will call that with the name of the method we were looking for this is so that you can respond to things dynamically as a meta programming technique we dig into that into meta programming video instead so we can of course reopen our user class now and add a new method like so so we reopen it at a status instance method and that just adds another entry as you can see here into the classes method table now another method we can take is we can define methods upon ticket instances so here's an example we create a me it's a new user you is a new user and then we define just on me a method called age with 30 inside if I call me dot age we get 30 back for call you dodged it's a no method error so how does this fit into the object model we looked at so far because remember before I said that only classes have methods will you obviously haven't added the age to the user class because it's not working on the you object so what's happening here a little diagram will help us out so at the top left we have the me object at the bottom left we have the you object and their class reference both point to the user class so where does this age method go it can't go in the class as we've just said so what does it do well Ruby creates a new special class which is called a singleton class or sometimes I met a class or a goon class and it adds the method there so this is the one that we got in blue so the method is now added onto this special class doesn't really have a name but one common notation is to put star and then the name of the object that that symbol could cast belongs to so how does this join into things we haven't actually put this into the diagram so this is how it looks behind the scenes really creates this singleton class but then what it does is it sets the superclass of this singleton class to user and it sets the class reference on the object to the singleton class now so instead of that class reference going directly from the object to user it goes via this singleton class and so that means that when we call me door age it goes look at the object what class is it arts a class of this singleton class is age there yes it is it can run it where as you object at the bottom left here that just goes straight up to the user class it doesn't have this singleton method or the singleton class now behind the scenes if you you start asking Ruby about stuff it's still going to come up as user rather than the singleton class and that's because Ruby's clever enough to hide all these implementation details for us and it only shows us what we pragmatically want to know so if you still say me dot class it will still say user now if we added singleton methods to the you object then it will get its own singleton class added into just like so so very very simple and just to reinforce that point if we now say me doc class or you class it will still be user despite having those singleton classes in the way so class methods won't believe it or not we've done all these singleton methods and classes this is a sohow class methods work now as I've said before only classes have methods so why is there this distinction in Ruby between instance methods and class methods well class methods are basically methods aren't available from each instance so you can't say me dot whatever instead you refer to them via the class directly itself and you may know these as static methods in other languages like Java or C++ so here's a very quick example we reopen our user class and we define self dot plural underscore name and we put a string in users and we can call it directly now upon the class so we can use the Doppler underscore name me doc Lorenz got a menu dr. olin scanning will not work this is a class method so here how does all this work them well if we look at this in relation to the Ruby object model this plural underscore name method isn't being added to the user class's method table since that's the instance methods of user so Ruby creates a meta class as we can see here with a star user in the middle it puts the method there and then why is everything up so that the meta class becomes the class of the user class I know this is all starting to sound a little bit complicated might require some rewatching so we've got our user class on the Left we've got our object and our class class on the right and we've added in this extra singleton class in the middle that has these class methods on so in a sense this is very much like doing the def me dot age but we're doing up at the class level now so in this sense you might be getting a feel for an important Factory Ruby's object model and that is that all methods are instance methods of some sort it just depends on where they get placed so the name equals and the name methods for example our instance methods on the user class but the plural underscore name method is just an instance method on users singleton class or it's meta class however you want to refer to that so before we look at how modules fit into this whole picture there's an important concept we need to look at called the default define II I'm not sure this actually has a technical name anywhere in the Ruby world but this is how seen it referred to some people refer to it as class with a k' but I think that could be a little bit confusing with some of the stuff we looked at earlier so let's go and have a look and something here so defining a method adds an entry to the method table of the current self right so we can see what this looks like we open up a user class and we say what is self and self is the current user class but if this is also then what's going on here so here we're defining both instruments and class methods both got the same name but the top one will become a class method or and it's this method on user singleton class and the one at the bottom is just a regular instance method but if we're currently in the context of self why is self dot status and status totally different things why is one creating a singleton class and wise-1 just adding it to the current method table and the answer here is that method definitions do not occur on self by default they are current something else called the default defining so when you invoke a method it does occur on self but definitions do not necessarily so the default define is where methods get to find when method definitions don't have a specific target and this default define e gets set to different things depending on the context so with a class definition block the default define e is the class itself that's straightforward but when we do def self dot status the method will be added to a singleton class of that self so just like when we added the aged singleton method to our me object for example so this idea of the default define e becomes a lot more important when we start playing with methods like instance eval and class eval we have instance eval we can run code dynamically in the context of the target object so let's look at an example of this we create a user object and then we go me dot instance eval so now the code in this block following instance eval is running in the context of the me object so we can say self cuz self is now the me object self dot name equals whatever in the block and then we can see name is all correct so that's all fine but now what if we start doing defining methods we open up me we define a method called age put age of 30 in there and now middle age is a method that returns 30 that doesn't seem you know too complicated at this point but if we move up to the class level it becomes a little bit more interesting so if we open up the user class and we say instance eval define gender well this hasn't added an instance method to the user class because we go meet gender it says there's no such method what it's actually done is its created a class method or as we now know a singleton method on users singleton class so we're going to play a bit more with eval methods in the meta programming video but what I want to get across here is there is a difference you need to look at where is being targeted by when you're when you're defining methods so in this case we're defining methods on users singleton class and not directly within user if we do want to get that behavior however we need to use class eval which acts a lot more like opening a class definition manually so this is a bit more like saying class user and then defining new instance methods so both self and the default define e in this case are the class itself so as I said we're going to play a lot more with this in the metaprogramming video this you just get a feel for the the structure of that singleton class so modules modules are defined in the official Ruby documentation as collections of methods and constants sounds a bit like a class doesn't it well modules are a bit like classes but without any instance creation capabilities so actually classes superclass is module it takes a lot of the stuff from modules adds extra things like instance creation so let's try and actually use a module as a collection of methods and constants so we create our own module here called my module we create a constants within equal constant in it called pi and this gets added to the modules constant table we add a method and called some method and then we try and use this stuff at the bottom here so my module colon colon PI colon colon just gives you kind of access into that namespace so we can get constants out that works fine but if we do my module dot sum method it doesn't work in kind of the same way that you know if you use the clasp this wouldn't work either so what we've done here in this module is we've created something that you would call an instance method much like you would have a class but in this case it's only accessible when you include this module into a class so let's try doing that we get a class called user we include my module and now you can call the some method instance method in this way so if we go back to this just to show the point we've got a module called my module is gone instance method called some method when we do the include than my module into user we can now use that method and this concept sometimes called mixing in and my module might well be called a mixin it's a handy way of blending methods together into classes so you might have lots of different modules and lots of different methods and then you can pick and choose from those modules and kind of give extra functionality to classes that you've got we're not going to focus on the applications of this technique here however because it's not really relevant to the object model so modules also support something else called module methods these are a bit like class methods with classes so for example we've got our module here my module I'm saying death self dot some underscore methods so this looks a lot more like a class method but we call it a module method in this case and so now we can say my module dot sum underscore method and it works fine however these won't get included when use include but they do provide a handy way to conveniently group methods together within a namespace so for example you can do this in Ruby math dot cosine 10 and unfortunately the argument here has to be in radians but math cos 10 so we haven't added cosines dirty to fix num or anything here we're just using this math module namespace as a way to store all these different functions essentially they act like methods but you know kind of mathematically they're basically functions so anyway back to our mix-ins how do these work in relation to the Ruby object model so let's bring up another code example so we've got a module here called naming methods and this has our get around setter we have a class called user and now instead of defining those instance methods directly within user we include them from the naming methods module and then we get the same sort of functionality that we had before but how does this work in terms of the Ruby object model well just before we get to that let's think about how this might work so what could happen when we're doing include naming methods is Ruby might look at the naming methods module and say right let's copy all of these methods into user that's not what's happening however we can prove that by doing something else we can reopen the module we can then add an extra instance method in there and when we do the me dot hello so it actually still gets this new thing we've added to the module so there must be a tie between the class to the module in some way and this is kind of important in terms of the object model as to how that works so what Ruby really does where the modules mixed into a class is it creates a special virtual class called an include class this is referred to internally as an eye class and then what it does is it points its instance variable and Method table references to the same ones as those in the module so let's get a better feel for this with the diagram so here's our before we're going to use a class at the top left and the superclass is object and then at the bottom right we've got our our module so this is our naming methods thing that's got our methods table with name equals name and hello in it how does all this work well we create this include class and we put it in the middle so it's a little bit like a singleton class but not it's for you know hooking up to modules what we do is just say we set the superclass of user to this special include class we set that superclass back to object so we're just pushing things into the inheritance chain here and then we kind of alias the methods table of that eye class to the methods table of the module so if you update the module everything gets updated because the eye class can still see that same method table so it all just works now before you know I let all of this mind boggling stuff sink in and I'm guessing you may need to watch this a few times I do want to look at something that's to include the Rubies commonly used that's called the extend method so we've include include makes an include class then becomes an implicit superclass of the class you're doing the include on and you can use that as a tongue twister if you like but extend or something similar but instead works on the object singleton class so let's take a really basic example if you use extend on a class you end up with class methods which remember are just methods on the classes singleton class so example time I've created a module here called class methods and I just have a simple instance method in here called hello I now open up our user class instead of doing include I do extend so the difference here is if I used include it would create that eye class and it would put it in the inheritance chain and so that means that all instances of user would get access to that modules instance methods so if I did me equals user new then me dot hello would be 42 but if I use extend it adds methods from the module to a singleton class on that object so you may need to kind of get your head around this a bit what this allows us to do is then they get added as class methods that's the way they look at the surface so we can go P user dot hello and we get access to it that way if I show you this practice on an object it may make a little bit more sense so we create another module here called singleton methods has the same hello method that returns 42 we create a string and then we say extend this string with the singleton methods so what's happening here is it says right string add all the methods from this module to your singleton class so now when we say string dot hello we get the correct response and all of this comes together in a very common Ruby pattern that allows a module to do both things so it can both add instance and class methods to a class for example many rails plugins do this for example so let's have a quick look at a very contrived example so I've got a module here called my functionality and in there I've got an instance method at the top I have a another method or just ignore for now cool self dot included and then I have a module underneath the my function attic module called class methods and in there I define instance method class math so what do we do lower it down here we create a class called my class and we include the my functionality module so that whole top module gets included into my class so how does all of this work well the first thing that happens is the modules instance methods get included into my class through the include class superclass thing that we talked about earlier so we get the instance method no problems that makes sense my class new door instance MEF that's come through from the module but we want to get class methods as well and we could do it with extend so we could do include my functionality and then extend my functionality colon colon class methods that would work fine but it's a little bit messy we must do it all in the one so if you include a model into a class or another module Ruby looks for a module method called included on that module looks for all that behind the scenes that was all happens implicitly and if it exists it calls it and passes in the class or module that is having the inclusion done to it so if you look at that method there death self dot included class that is getting called when we do that include lower down and it passes in the my class as class and then what we can do is we can say class dot extend class methods so rather having separately include my functionality and extend my functionality colon colon class methods we can instead use this behind-the-scenes hook to do it all for us and here's a little diagram to kind of show you how it ends up looking you may need to let this steep in and pulls this for a moment but basically have the my functionality module at the right we have the my functionality class methods module at the bottom and you can see the different ways that these hook into the my class that's at the top left after doing the include which is cut all the rut stuff on the right and the extend all the stuff at the bottom left so are you confused yet you should be and but luckily we're at the end now so you can ponder on this a bit more but once you get a feel of how these relationships work you'll be a lot more confident work and we've really classes objects and modules and reading further information about this because this is you know we've dug in quite a way but there is more that you can read and learn about this topic and once you get a feel for all these relationships you hopefully will become a lot more confident with your further development of Ruby and some of the quirks you'll bump into you'll think oh yes it's because the internal representation is such-and-such so I'm going to leave you there good luck getting through this but remember we have the forum if you'll ask questions and I can extend an elaborate on this in a live Q&A if you want me to so thank you for watching
Info
Channel: Peter Cooper
Views: 40,317
Rating: undefined out of 5
Keywords: ruby, objects, object orientation, Object Model
Id: by5fFOBhtPQ
Channel Id: undefined
Length: 34min 0sec (2040 seconds)
Published: Wed Jul 30 2014
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.