Blog #23
super
and calling super()
?A call to super
invokes the parent method with the same arguments that were passed to the child method. An error will therefore occur if the arguments passed to the child method don’t match what the parent is expecting.
A call to super()
invokes the parent method without any arguments, as presumably expected. As always, being explicit in your code is a good thing.
supper
example:
class Parent
def say(message)
p message
end
end
class Child < Parent
def say(message)
super
end
end
Child.new.say('Hello world!') # => "Hello world!"
supper()
example:
class Parent
def say
p "I'm the parent"
class Child < Parent
def say(message)
super
end
end
Child.new.say('Hello!') # => ArgumentError (wrong number of arguments (given 1, expected 0))
class Parent
def say
p "I'm the parent"
end
end
class Child < Parent
def say(message)
super()
end
end
Child.new.say('Hi!') # => "I'm the parent"
class
and a module
?Modules are collections of methods and constants. They cannot generate instances. Classes may generate instances (objects), and have per-instance state (instance variables).
Modules may be mixed in to classes and other modules. The mixed in module’s constants and methods blend into that class’s own, augmenting the class’s functionality. Classes, however, cannot be mixed in to anything.
A class may inherit from another class, but not from a module.
A module may not inherit from anything.
module Swimmable
def swim
puts "I'm swimming!"
end
def self.module_swim_method
puts 'module_swim_method'
end
end
module Flyable
include Swimmable
def fly
puts "I'm flying!"
end
end
class Duck
include Flyable
end
duck = Duck.new
duck.swim # Output: I'm swimming!
duck.fly # Output: I'm flying!
duck.module_swim_method # Output: NoMethodError
Swimmable.module_swim_method # Output: module_swim_method
Flyable.module_swim_method # Output: NoMethodError
"false"
?true ? "true" : "false"
false ? "true" : "false"
nil ? "true" : "false"
1 ? "true" : "false"
0 ? "true" : "false"
"false" ? "true" : "false"
"" ? "true" : "false"
[] ? "true" : "false"
In Ruby, the only values that evaluate to false are false
and nil
. Everything else – even zero (0) and an empty array ([]) – evaluates to true.
This comes as a real surprise to programmers who have previously been working in other languages like JavaScript.
(Thanks to Ruby Gotchas for this question.)
-> (a) {p a}["Hello world"]
Yes, it’s valid. Here’s how to understand what it does:
The -> is often called the “stabby proc”. It’s also called the “stabby lambda”, as it creates a new Proc instance that is a lambda. All lambdas are Procs, but not all Procs are lambdas. There are some slight differences between the two.)
This particular Proc takes one parameter (namely, a
). When the Proc is called, Ruby executes the block p a
, which is the equivalent of puts(a.inspect)
(a subtle, but useful, difference which is why p
is sometimes better than puts
for debugging). So this Proc simply prints out the string that is passed to it.
You can call a Proc by using either the call
method on Proc, or by using the square bracket syntax, so this line of code also invokes the Proc and passes it the string “Hello World”.
So putting that all together, this line of code (a) creates a Proc that takes a single parameter a
which it prints out and (b) invokes that Proc and passes it the string “Hello world”. So, in short, this line of code prints “Hello World”.
clone
and dup
?Object#dup
creates a shallow copy of an object. For example, it will not copy any mixed-in module methods, whereas Object#clone
will. This can be shown with the following code example:
class Klass
attr_accessor :str
end
module Foo
def foo; 'foo'; end
end
s1 = Klass.new #=> #
s1.extend(Foo) #=> #
s1.foo #=> "foo"
s2 = s1.clone #=> #
s2.foo #=> "foo"
s3 = s1.dup #=> #
s3.foo #=> NoMethodError: undefined method `foo' for #
extend
and include
?include
mixes in specified module methods as instance methods in the target classextend
mixes in specified module methods as class methods in the target classGiven the following class definitions:
module ReusableModule
def module_method
puts "Module Method: Hi there! I'm a module method"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
Here’s how ClassThatIncludes
behaves:
# A class method does not exist
>> ClassThatIncludes.module_method
NoMethodError: undefined method `module_method' for ClassThatIncludes:Class
# A valid instance method exists
>> ClassThatIncludes.new.module_method
Module Method: Hi there! I'm a module method
=> nil
Here’s how ClassThatExtends
behaves:
# A valid class method exists
>> ClassThatExtends.module_method
Module Method: Hi there! I'm a module method
=> nil
# An instance method does not exist
ClassThatExtends.new.module_method
NoMethodError: undefined method `module_method' for #<ClassThatExtends:0x007ffa1e0317e8>
We should mention that object.extend ExampleModule
makes ExampleModule
methods available as singleton methods in the object.
private
and protected
?class A
def pub
1
end
def use_pri
pri
end
def use_pro
pro
end
private
def pri
2
end
protected
def pro
3
end
end
class B < A
def call_a_pub
A.new.pub
end
def call_a_pri
A.new.pri
end
def call_a_pro
A.new.pro
end
end
A.new.pub # => 1
A.new.use_pri # => 2
A.new.use_pro # => 3
A.new.pri # => NoMethodError: private method `pri' called for #<A:0x00000001085f1f50>
A.new.pro # => NoMethodError: protected method `pro' called for #<A:0x00000001085b8cf0>
B.new.call_a_pub # => 1
B.new.use_pri # => 2
B.new.use_pro # => 3
B.new.call_a_pri # => NoMethodError: private method `pri' called for #<A:0x00000001083bff70>
B.new.call_a_pro # => 3
*
and **
arguments?*r
captures positional arguments as an array.
def a(*r)
p r
end
a(1, 2, 3) # Output: [1, 2, 3]
**r
captures keyword arguments as a hash.
def b(**r)
p r
end
b(name: "Alice", age: 30) # Output: {:name=>"Alice", :age=>30}
proc
, block
, lambda
Nature:
Block
: Not an object, passed to methods.Proc
: An object that can be stored and called.Lambda
: A type of Proc with stricter rules.Return Behavior:
Block
: Returns from the method that called it.Proc
: Returns from the enclosing method.Lambda
: Returns from the lambda itself.Argument Checking:
Block
: Does not check the number of arguments.Proc
: Does not check the number of arguments.Lambda
: Checks the number of arguments.Example:
Blocks
[1, 2, 3].each do |num|
puts num * 2
end
# or using {}
[1, 2, 3].each { |num| puts num * 2 }
Procs
my_proc = Proc.new { |x| x * 2 }
puts my_proc.call(5) # Output: 10
Lambdas
my_lambda = ->(x) { x * 2 }
puts my_lambda.call(5) # Output: 10
# Parameter check example
my_lambda_with_check = lambda { |x| x * 2 }
my_lambda_with_check.call(5) # Works
# my_lambda_with_check.call # Raises an ArgumentError
String
a = "hello"
b = "hello"
# them object ID not equal
a.object_id # => 73760
b.object_id # => 73780
# but I can use freeze
a = "hello".freeze
b = "hello".freeze
a.object_id # => 73800
b.object_id # => 73800
Integer
5.object_id = 11 # 5 * 2 + 1
22.object_id = 45 # 22 * 2 + 1
Float
a = 1.2
b = 1.2
a.object_id == b.object_id # true
Array
a = [1, 2, 3]
b = [1, 2, 3]
a.object_id == b.object_id # false
Symbol
a = :hello
b = :hello
a.object_id == b.object_id # true
Hash
a = {x: 123}
b = {x: 123}
a.object_id == b.object_id # false
Nil
nil.object_id = 4 # always
nil.object_id = 8 # always with ruby_64
https://stackoverflow.com/questions/31816149/difference-between-calling-super-and-calling-super
https://www.toptal.com/ruby/interview-questions
https://www.reddit.com/r/ruby/comments/ojsq9z/when_to_use_protected_and_private/