Class Methods & Variables
8252 ワード
When calling an instance method like
One would therefore think it’s safe to assume that an instance method is always preceded by a
which is in turn preceded by the object that is calling the method.
Why, then, did this code work in the previous example?
Isn’t
This can be compared to spoken language. If you were asking Diego to tell us his name, you might say to him “Diego, tell us your name.”
But if you were asking me to tell you my name, you’d likely say “Tell me your name”.
Yes, you could have said “You, tell me your name,” but that would have been redundant. “You” isimplicit in “Tell me your name”.
Similarly, when you call an instance method from within a class, there is an implicit object being called: itself.
An object can refer to itself using the
When you call
And since Ruby is all about removing any unnecessary syntax,
An instance variable like
But what if you wanted a variable that was shared across all instances of a class? Almost like… a class variable.
Boom is right.
A class variable’s syntax is twice as cool as an instance variable, because it has two
Let’s see how one might use a class variable.
Unfortunately, class variables can’t be accessed using
Initialize two instances of an employee to see this working.
Great, now this
Class variables are used considerably less frequently than instance variables.
Unlike the
If you break this apart, you’ll see two class variables,
Every time a new customer is instantiated, an instance variable of
Immediately afterwards, the
This way, the
By assigning the class variable to the instance variable
Similarly,
After a new customer is initialized,
Unfortunately, we’re left without an appropriate interface for accessing
It wouldn’t make sense to create a
If only there were something else...
Class variables can be especially powerful when coupled with class methods.
Class methods differ from instance methods in that they are called directly on the class name, like so:
These are used when you need to call a method that doesn’t apply to a specific instance of a class.
Say you need a method to retrieve all the customers you’ve created so far. This method could be called
Defining a class method works just like defining an instance method, except it must be preceded by
Now, if at any point you’d like to retrieve an Array of all existing customers, you can simply call the class method.
withdraw_securely
, the syntax generally looks something like this: object.method_being_called(arguments)
One would therefore think it’s safe to assume that an instance method is always preceded by a
.
, which is in turn preceded by the object that is calling the method.
Why, then, did this code work in the previous example?
# from inside the Customer class
def withdraw_securely(amount, password)
if password == @password
remove_funds(amount)
end
end
Isn’t
remove_funds
also an instance method? Why is it suddenly exempt from following the same object.
method_being_called
syntax just because it’s inside a method? This can be compared to spoken language. If you were asking Diego to tell us his name, you might say to him “Diego, tell us your name.”
But if you were asking me to tell you my name, you’d likely say “Tell me your name”.
Yes, you could have said “You, tell me your name,” but that would have been redundant. “You” isimplicit in “Tell me your name”.
Similarly, when you call an instance method from within a class, there is an implicit object being called: itself.
# from inside the Customer class
def withdraw_securely(amount, password)
if password == @password
self.remove_funds(amount)
end
end
An object can refer to itself using the
self
keyword. Think of it as an object’s way of saying “me” or “I”. When you call
remove_funds
from within the Customer
class, you’re saying “remove these funds from myself”. And since Ruby is all about removing any unnecessary syntax,
self
in this context is implicit, and can be left out entirely. An instance variable like
@password
is scoped to a particular instance of a class. But what if you wanted a variable that was shared across all instances of a class? Almost like… a class variable.
@@check_out_this_cool_class_variable = "boom."
Boom is right.
A class variable’s syntax is twice as cool as an instance variable, because it has two
@
’s instead of just one. Let’s see how one might use a class variable.
class Employee
@@bank = "Udacity International Bank"
def bank
@@bank
end
end
Unfortunately, class variables can’t be accessed using
attr_accessor
, so you’ll need to create your own bank
getter method in this case. Initialize two instances of an employee to see this working.
elana = Employee.new
# => #<Employee:0x007fcdb48c19d0>
corey = Employee.new
# => #<Employee:0x00nfbdm132ejd9>
elana.bank
# => "Udacity International Bank"
corey.bank
# => "Udacity International Bank"
Great, now this
@@bank
class variable is shared across all instances of an Employee
class. But… Why?
Class variables are used considerably less frequently than instance variables.
Unlike the
public
keyword, though, there are some practical use cases for class variables. Here are two of those use cases. class Customer
attr_reader :id
@@id = 1
@@customers = []
def initialize
@id = @@id
@@id += 1
@@customers << self
end
end
If you break this apart, you’ll see two class variables,
@@id
and @@customers
. Every time a new customer is instantiated, an instance variable of
@id
is set to the value of theclass variable @@id
. Immediately afterwards, the
@@id
class variable is incremented by one. larry = Customer.new
# => #<Customer:0x007faaba8a6aa8 @id=1>
christine = Customer.new
# => #<Customer:0x007faaba8a6aa8 @id=2>
larry.id
# => 1
christine.id
# => 2
This way, the
Customer
class can keep track of the total number of customer objects that have been created. By assigning the class variable to the instance variable
@id
, you are capturing the current ID number from when that particular customer object was created. Similarly,
@@customers
in this case is an Array that holds all the customer objects that have ever been created. After a new customer is initialized,
self
, the particular instance currently being used, is pushed into this @@customers
Array. Unfortunately, we’re left without an appropriate interface for accessing
@@customers
. It wouldn’t make sense to create a
customers
instance method, since an Array of customers isn’t really a property of a particular customer. If only there were something else...
Class variables can be especially powerful when coupled with class methods.
Class methods differ from instance methods in that they are called directly on the class name, like so:
Customer.this_is_a_class_method
These are used when you need to call a method that doesn’t apply to a specific instance of a class.
Say you need a method to retrieve all the customers you’ve created so far. This method could be called
all
. Defining a class method works just like defining an instance method, except it must be preceded by
self.
class Customer
attr_reader :id
@@id = 1
@@customers = []
# ...
def initialize
@id = @@id
@@id += 1
@@customers << self
end
def self.all
@@customers
end
end
Now, if at any point you’d like to retrieve an Array of all existing customers, you can simply call the class method.
Customer.all
# => [#<Customer:0x007faaba84c148 @id=1>, #<Customer:0x007faaba82fe30 @id=2>]