Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Inside a class definition (e.g. <code>class User ...</code>), <code>def encrypt ...</code> defines an <em>instance method</em>, whereas <code>def self.encrypt ...</code> defines a <em>class method</em>.</p> <h2>Defining instance methods and class methods</h2> <p>Suppose we defined the User class like this:</p> <pre><code>class User def initialize(name) @name_instance_variable = name end # This is an instance method definition, creating a method called `encrypt` # on instances of the User class. def encrypt puts "Received User#encrypt instance method.\n" + "- `self` is an instance of #{ self.class }.\n" + "- `@name_instance_variable` is #{ @name_instance_variable.inspect }.\n" end # This is a class method definition, creating a method called `encrypt` on # the User class itself. def self.encrypt puts "Received User.encrypt class method.\n" + "- `self` is an instance of #{ self.class }.\n" + "- `@name_instance_variable` is #{ @name_instance_variable.inspect }.\n" end end </code></pre> <h3>Invoking an instance method</h3> <p>Now we can create an <em>instance</em> of User with the constructor <code>User.new</code>, which (automatically) invokes <code>initialize</code> above:</p> <pre><code>my_user = User.new("Tim") </code></pre> <p>In <code>initialize</code>, the value we gave to the constructor is assigned to the <em>instance variable</em> <code>@name_instance_variable</code>.</p> <p>Now we can invoke <em>instance methods</em> on <code>my_user</code>, our <em>instance</em> of the User class:</p> <pre><code>my_user.encrypt # =&gt; Received User#encrypt instance method. # - `self` is an instance of User. # - `@name_instance_variable` is "Tim". </code></pre> <p>We can create another instance and give a different value to the constructor:</p> <pre><code>User.new("Jordan").encrypt # =&gt; Received User#encrypt instance method. # - `self` is an instance of User. # - `@name_instance_variable` is "Jordan". </code></pre> <h3>Invoking a class method:</h3> <p>We can also invoke <em>class methods</em> on the User <em>class</em>:</p> <pre><code>User.encrypt # =&gt; Received User.encrypt class method. # - `self` is an instance of Class. # - `@name_instance_variable` is nil. </code></pre> <p>We get <code>nil</code> for <code>@name_instance_variable</code> because the <em>class</em> method does not have access to any of the <em>instances</em> we created, and we haven't done anything that would assign a value to it.</p> <h3>Another class method, and using one class method inside another</h3> <p><em>After</em> we've created the User class, we can also define a new class method like this:</p> <pre><code>def User.create_remember_token puts "Received User.create_remember_token class method." # Now let's use the User.encrypt class method from within this method. encrypt # We could also write this, because inside this class method `self` refers # to the User class itself: # # self.encrypt # # This is equivalent too--almost (the difference appears when you use # inheritance, i.e. create a subclass of User, but that's beyond the scope # of this answer): # # User.encrypt # end </code></pre> <p>...that's equivalent (but not necessarily preferable) to:</p> <pre><code>class User def self.create_remember_token # ... end end </code></pre> <p>Now we have a <code>User.create_remember_token</code> class method, which works like this:</p> <pre><code>User.create_remember_token # =&gt; Received User.create_remember_token class method. # Received User.encrypt class method. # - `self` is an instance of Class. # - `@name_instance_variable` is nil. </code></pre> <h3>Defining another instance method, and using instance methods inside other instance methods</h3> <p>Suppose we defined another instance method:</p> <pre><code>class User # An instance method this time: def create_remember_token puts "Received User#create_remember_token instance method.\n" "- `@name_instance_variable` is #{ @name_instance_variable }." encrypt # We could also write this, because inside this instance method `self` # refers to this instance of User: # # self.encrypt # end end </code></pre> <p>Now we have a <code>User#create_remember_token</code> instance method, which does this:</p> <pre><code>my_user = User.new("Alice") my_user.create_remember_token # =&gt; Received User#create_remember_token instance method. # - `@name_instance_variable` is "Alice." # Received User#encrypt instance method. # - `self` is an instance of User. # - `@name_instance_variable` is "Alice". </code></pre> <h3>Using class methods within instance methods</h3> <p>Finally, there are two ways to invoke <em>class</em> methods from within <em>instance</em> methods. Suppose we defined our <em>instance</em> method like this instead:</p> <pre><code>class User def create_remember_token puts "Received User#create_remember_token instance method." "- `@name_instance_variable` is #{ @name_instance_variable }." # Since `self` refers to this instance of User, `self.class` equals # the User class itself. self.class.encrypt # That's is (almost) equivalent to this: # # User.encrypt # # ("Almost" again because of the inheritance issue mentioned above.) # end end </code></pre> <p>Now it will work like this:</p> <pre><code>User.new("Bob").create_remember_token # =&gt; Received User#create_remember_token instance method. # - `@name_instance_variable` is "Alice." # Received User.encrypt class method. # - `self` is an instance of Class. # - `@name_instance_variable` is nil. </code></pre> <p>Note that even though we invoked the <em>class</em> method <code>User.encrypt</code> inside of the <em>instance</em> method <code>User#encrypt</code>, the <em>instance variable</em> <code>@name_instance_variable</code> is still not available inside the <em>class method</em>.</p> <h3>When to use a class method</h3> <p>So why do class methods exist? Because you aren't always working with an <em>instance</em>.</p> <p>There are good examples of this in Rails. Suppose we have a "Comment" model. <code>Comment#update_attributes</code> is an <em>instance method</em> because it works with an instance of Comment. It knows about the instance's attributes and its internal <em>state</em>. When you use <code>update_attributes</code> you know that you're making changes to that instance of Comment.</p> <p><code>Comment.find</code>, however, is a <em>class method</em>. When you use <code>Comment.find</code> you don't have an instance of Comment (yet). If <code>find</code> was an <em>instance</em> method we wouldn't be able to use it without first creating an instance:</p> <pre><code>id = 6 comment = Comment.new.find(id) # =&gt; #&lt;Comment id: 6, ...&gt; </code></pre> <p>...and that doesn't make much sense.</p> <p>Rails could have done this another way, like defining a CommentFinder class, which makes a <em>little</em> more sense:</p> <pre><code>comment_finder = CommentFinder.new comment = comment_finder.find(id) # =&gt; #&lt;Comment id: 6, ...&gt; </code></pre> <p>...and is actually pretty common in some languages (and even in some Ruby libraries; the popular <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" rel="nofollow">factory pattern</a> does this). But in Rails they've decided to make this simpler by making this functionality a <em>class method</em> of the Comment class, so we can just do this:</p> <pre><code>comment = Comment.find(id) # =&gt; #&lt;Comment id: 6, ...&gt; </code></pre> <h2>Final notes</h2> <ol> <li><p>You might've noticed that I keep referring to <em>instance methods</em> like this: <code>User#encode</code> and <em>class methods</em> like this: <code>User.encode</code>. This is a convention you'll see throughout Ruby and Rails' documentation and books and articles about both. A <code>#</code> after the class name means it's an instance method and a <code>.</code> means it's a class method.</p></li> <li><p>Ruby is a "message-passing" language. You don't really need to worry about the distinction, but knowing this is handy because of some of the terminology you might run into. When we write <code>my_user.encode_video</code> we're technically <em>sending</em> the "message" <code>encode_video</code> to the <code>my_user</code> object. <code>my_user</code> <em>receives</em> the message <code>encode_video</code>.</p> <p>Colloquially, we often say "I <em>called</em> the <code>encode</code> method" or "this code <em>invokes</em> <code>encode</code>," and it's fine to use those terms instead (and in truth more developers will probably understand them). You'll probably find code before too long, though, that does something like <code>my_user.send(:encode_video)</code>, or even <code>type = "video"; ... my_user.send("encode_#{type}")</code> which makes more sense when you understand that "send" means "call" or "invoke."</p></li> <li><p>Ruby is a very flexible language. Above in some of the output I wrote, "<code>self</code> is an instance of Class". That's not a mistake--in Ruby, even classes are objects, and any class you create will be an instance of the class named Class. There are even ways to define instance methods and instance variables on a class itself (rather than instances of it), but that's way beyond the scope of this answer. If you're dying of curiosity, google "<a href="https://www.google.com/search?q=eigenclass" rel="nofollow">eigenclass</a>."</p></li> </ol> <p>I hope that's helpful.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload