Local variables: begins with an underscore _ or lower case letter.
Global variables: begins with $.
Instance variables: begins with @.
Class variables: begins with @@.
Constants
Constants begin with a capital letter. Ruby has beforehand defined several constants(known as predefined-constants), for example: RUBY_VERSION, RUBY_PlATFORM, ARGV, and so on.
Assign
Ruby can simultaneously assign values to several variables.
1 2
a, b, c = 1, 2, 3 pp(a, b, c) #=> 1, 2, 3
Redundant values will be ignored.
1 2
a, b = 1, 2, 3, 4, 5 pp(a, b) #=> 1, 2
The lacking values will be filled with nil.
1 2
a, b, c = 1, 2 pp(a, b, c) #=> 1, 2, nil
Prefixes one of these variables with * for capturing all redundant values with array format.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
*a, b, c = 1, 2, 3, 4 pp(a, b, c) #=> [1, 2], b, c
a, *b, c = 1, 2, 3, 4 pp(a, b, c) #=> 1, [2, 3], 4
a, b, *c = 1, 2, 3, 4 pp(a, b, c) #=> 1, 2, [3, 4]
a, *b, c = 1, 2 pp(a, b, c) #=> 1, [], 2
a, *b, c = 1 pp(a, b, c) #=> 1, [], nil
a, *b, c = nil pp(a, b, c) #=> nil, [], nil
Assigning an array to several variables has the equivalence of assigning several values unwrapped from the arr to these variables.
1 2
a, b, c = [1, 2, 3] # the same as `a, b, c = 1, 2, 3` pp(a, b, c) #=> 1, 2, 3
Conditions
Ruby has two groups of logical operators: &&, ||, ! and and, or, not. But the former has higher priority.
If the scope of the condition has only one line of code, Usually, we write them on one line.
1 2 3 4 5 6 7 8 9
age = 20
# Not good. if age > 18 puts 'You are an adult.' end
# Good. puts 'You are an adult.'if age > 18
Loop
Ruby has six kinds of loops, times, while, each, for, until, and loop.
The for is just a syntactic sugar of the each.
Ruby has tree loop-condition symbols:
break: Jumps out of the loop
next: Jumps to next cycle.
redo: Repeats current cycle.
Functions
Invoking Functions
In Ruby, all function calls must have a receiver. You can think of invoking a method as sending a message to a receiver.
1
print(100) #=> 100
The print function has an implicit receiver: self.
In Ruby, many operators are actually functions. For example: +, -, [], etc.
As you can see, we can use . or :: to invoke a class method. But we recommend to use ..
functional method
1
puts 'Hello, world.'
Superficially, the function has no receivers. We don’t need to specify a receiver for the function when calling it. The invoking result doesn’t changed with difference receivers.
Function Definition
Ruby functions implicitly return the last expression’s value when not using the return keyword.
1 2 3 4 5 6 7 8
defmethod1 1 + 1 end pp(method1) #=> 2
defexecute2 end pp(method2) #=> nil
Ruby methods can define default values for arguments. But you must specify default values beginning with the right of the argument list.
1 2 3 4 5
defmethod(a, b=200, c=300) puts a, b, c end
method(100) #=> 100, 200, 300
Ruby methods with variadic arguments. Just like assign values to multiple variables.
1 2 3 4
defmethod(a, *b, c) pp(a, b, c) end method 1, 2, 3, 4#=> 1, [2, 3], 4
Ruby methods with named arguments.
Named arguments can setup default values with format name: default.
Cannot pass undefined named arguments.
1 2 3 4 5
defmethod(a:, b:1, c:2) pp(a, b, c) end
method b:200#=> nil, 200, 2
Ruby methods with combination of named arguments and normal arguments.
The method must firstly define normal arguments.
1 2 3 4 5 6 7 8 9
defmethod(a, b:0) pp(a, b) end method(10, b:20) #=> 10, 20
# manually create accessing methods. defage @age end
defage=(value) @age = age end
definitialize(name, age:100, weight:) @name = name @age = age @weight = weight end end
me = Person('csl', age:18, weight:85.5)
Special variable self
The self is a predefined-variable by Swift.
The self within instance methods of a class represents the instance itself on run-time.
1 2 3 4 5 6 7 8 9 10 11
classPerson definitialize end
defdump puts self end end
me = Person.new me.dump #=> #<Person:0x000000014500f550>
Class Methods
Ruby classes have four ways to define a class method.
class << class-name ~ end
1 2 3 4 5 6
class << Person defhello(name) puts "#{name} said hello." end end Person.hello 'csl'#=> csl said hello.
defines class << self ~ end in the definition body of the class.
1 2 3 4 5 6 7 8
classPerson class << self defhello(name) puts "#{name} said hello." end end end Person.hello 'csl'#=> csl said hello.
def class-name.method-name ~ end
1 2 3 4
defPerson.hello(name) puts "#{name} said hello." end Person.hello 'csl'#=> csl said hello.
defines def self.method-name ~ end in the definition body of the class.
1 2 3 4 5 6
classPerson defself.hello(name) puts "#{name} said hello." end end Person.hello 'csl'#=> csl said hello.
The class defined by class << class-name ~ end is known as singleton class, the methods defined within the class are known as singleton method.
Class Constants
Defines constants for classes. As mentioned above, constants begins with a capital letter or all letters are capital.
1 2 3 4 5
classComputer VERSION = '1.0.0' end
puts Computer::VERSION#=> 1.0.0
Class Variables
Defines class variables
Begins with @@
All instances can access class variables of its class.
The same as instance variables, class variables also need declare writers and readers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classPerson @@amount = 0
definitialize @@amount += 1 end
defself.amount @@amount end
defself.amount=(value) @@amount = value end end
10.times { Person.new } puts Person.amount #=> 10
Access Levels
Ruby has three access levels:
public
Exposes this method in the format of instance method
private
You cannot invoke this method with a specified receiver. (You can only invoke this method with the default receiver, so this method cannot be accessed outside its instance).
protected
The methods of protected access level can be accessed as instance methods by its class and all subclasses.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classPerson defsay puts 'Hello, World.' end
public:say
defeat puts 'Eating food.' end
private:eat
end
me = Person.new
me.say #=> Hello, World. me.eat #=> Error.
Two ways to specify access levels in batches.
Specifies multiple methods at the same time.
1 2 3 4 5 6 7 8 9
classPerson
private:method1, :method2
defmethod1; end
defmethod2; end
end
Sets up an access level without any arguments, all the methods defined below the statement will be the access level.
1 2 3 4 5 6 7 8 9 10 11 12
classPerson
public# The methods defined below this line will be set up with `public` access level.
defpublic1; end defpublic2; end
private
defprivate1; end defprivate2; end end
The default access level is public when you do not explicitly specify any access level. There is an exception that the initialized method is defaulted to private.
Class Extensions
We can redeclare an already defined class to extend methods for the class.
1 2 3 4 5 6 7 8 9
classString defcount_word arr = self.split(/\s+/)
return arr.size end end
p "My name is csl".count_word #=> 4
Inheritance
Defines a new class inherited from another class in the format of class class-name < super-class-name
If you define a new class without specifying a superclass, the default inherited class is Object.
If you override a method inherited from its superclass, you can use super to reinvoke superclass’s method in the definition scope of the method.
1 2 3 4 5 6
classRingArray < Array def[](i) idx = i % size super(idx) #=> Utilizes superclass implementation. end end
alias & undef
In Ruby, we can use alias to provide a new meaning name for an already defined method.
Alternatively, before redefining a method from the super class, you can alias the old method to save its functionality for using later.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classPerson defsay puts "I'm a person." end end
classStudent < Person
alias old_say say
defsay puts "I'm a student." end end
me = Student.new
me.say #=> I'm a student. me.old_say #=> I'm a person.
undef can be used to remove methods definitions. You can use it to remove methods definitions of super classes.
1 2 3 4 5 6 7 8 9 10 11 12 13
classPerson defsay puts "I'm a person." end end
classStudent < Person undefsay end
me = Student.new
me.say #=> undefined method `say`
Singleton Class
Every class we defined in Ruby are instances of BaseObject. We can use class << Student to extend class methods for the class Student.
Modules
If we say classes include data and behaviors, the Modules only include behaviors.
Modules can’t have instances.
Modules can’t be inherited.
Module Methods
Sometimes, some methods or variables are about a special area, like math calculation, we can collect them into an isolated module for easily using.
Using module_function can mark the method get as a module method, then we can access it directly by the Api type.
No marked functions can only be used in the module inner or be included by other classes.
Mix-in
A class can include a module to inheritance all instance methods defined in the module.
1 2 3 4 5 6 7 8 9 10 11 12
moduleAnimal defrun p "I'm running" end end
classPerson includeAnimal end
me = Person.new me.run # I'm running
Invoking the Person.ancestors method to look up all its ancestors, we can find the Animal module.
1
p Person.ancestors # [Person, Animal, Object, Kernel, BasicObject]
Ruby utilize the class inheritance to implement Mix-in naturally. But the module isn’t the real super class, it’s virtual. Accessing the Person.superclass, you can find that its superclass is still the object class.
Extend an instance
We have learned how to manually extend an instance’s singleton class, now we can use obj.extend(ModuleA) to extend it in bulk.
1 2 3 4 5 6 7 8 9 10 11 12
moduleCodable defencode end
defdecode end end
path = '/list' path.extend(Codable)
path.encode
Operators
In Ruby, almost all operators are instance methods, so we can easily override or define new operators for our types.
Binary Operators
Ruby disables overriding these operators: ::, &&, ||, .., ..., ?:, not, =, and, or
Unary Operators
We can only define these four kinds of unary operators: +, -, ~, !. They are defined separately by functions of names +@, -@, ~@ and !@.
Subscript Operators
Using two functions def [](index) and def []=(index, value) to define subscript for your types.
Block
Execute a block
Using the syntax yield to call the block passed in the function.
1 2 3 4 5 6 7 8
defexecute yield end
execute do puts 'test' end # test
Creating a block instance
1 2 3 4 5
hello = Proc.new do |name| puts "Hello, #{name}" end
hello.call("Ruby")
If a method’s last argument is prefixed with &, the block passed into the method when invoking will be assigned to the last argument.
1 2 3 4 5 6 7 8 9 10
defexecute(value, &block) do if block block.call(value) end end
execute 100do |value| puts value end # 100
Tips
Using Class.new can create a new class dynamically.
1 2 3 4 5 6 7 8 9
classPerson defsay(words) p "Say: #{words}" end end
Student = Class.new(Person) me = Student.new me.say 'Hello'#=> Say: Hello
Using %w(words) can generate an array from a literal string.
As you can see, the objc.method_name will access the outer constant, its context is external. The class << object will enter the inner of the objc’s singleton class, so we can access its inner constants.
Concepts
You can think that the notation class is used to open the context of classes, of course, it would create a new class by the way if the class hasn’t been created yet.
Instance variables in Ruby have no relation with its class. That means two objects of a class can have absolutely different instance variables. You can think of instance variables in Ruby as the key-value storage.