📜 ⬆️ ⬇️

Let's beat Ruby together! Drop ten

In this drop, we will once again delve into the PLO, figuring out new methods of working with classes, objects, modules that will definitely come in handy in serious programming.

Multiple constructors


What if we want to have multiple constructors for an object? Nothing prevents us from creating additional class methods that return new objects. In the following example, we describe cats with five parameters: weight, height, and three per color. We will create additional methods that define certain types of cats “by default” (for example, a black cat or a fat cat):

class SuperCat

def initialize ( height, weight, tail_color, head_color, legs_color )
@height , @weight , @tail_color , @head_color , @legs_color = height, weight, tail_color, head_color, legs_color
end

def
SuperCat . white_cat ( height, weight )
new ( height, weight, "white" , "white" , "white" )
end

def
SuperCat . black_cat ( height, weight )
new ( height, weight, "black" , "black" , "black" )
end

def
SuperCat . big_cat ( tail_color, head_color, legs_color )
new ( 100, 100, tail_color, head_color, legs_color )
end

end
a = SuperCat . new ( 10, 15, "white" , "black" , "white" )
b = SuperCat . black_cat ( 13, 20 )
c = SuperCat . big_cat ( "white" , "red" , "red" )
p ( a ) ; p ( b ) ; p ( c )

')
Does the word “constructor” take place here? We will leave this question to lawyers :)

The development of designers


Objects are becoming more complex, they collect more and more attributes that must be initialized when creating an object. The constructs responsible for this become lengthy and burdensome, forcing us to recalculate the parameters and wrap the lines.

One way to handle this complexity is to pass a block to the initialize method. Then we can use the block to initialize the object. We will use the instance_eval method instead of eval:
class HyperCat
attr_accessor :name ,
:height , :weight , :age ,
:tail_color , :head_color , :legs_color

def initialize ( &block )
instance_eval &block
end

# ...
end

pussy = HyperCat . new do
self
. name = "Pussy"
self . height = 10
self . weight = 12
self . age = 3.2
self . tail_color = "gray"
self . head_color = "gray"
self . legs_color = "white"
end

p pussy

We use accessors in attributes, so it’s easier to pass values ​​to them. We also need to refer to self , because the value assignment method always takes an explicit receiver to create a local variable.

Method access control


In Ruby, an object is basically determined by the interface it provides, the method by which it becomes available to others. However, when writing a class, we often need auxiliary methods used inside the class, but dangerous if they are accessible from the outside. This is where the Module private method will help us.

We can use private two ways. If you call private without parameters in the body of the class, all the methods below will become private. Or you can pass the list of methods as symbols as private parameters:
class Bank
def open_safe
# ...
end

def
close_safe
# ...
end

private :open_safe , :close_safe

def make_withdrawal ( amount )
if access_allowed
open_safe
get_cash ( amount )
close_safe
end
end

# -

private

def get_cash
# ...
end

def
access_allowed
# ...
end
end


Copying objects


The clone and dup methods create copies of the caller. The dup method only copies the contents of an object, while clone takes things like the singleton classes associated with an object:
s1 = "cat"

def s1 . upcase
"CaT"
end

s1_dup = s1. dup
s1_clone = s1. clone
s1 #=> "cat"
s1_dup. upcase #=> "CAT" ( )
s1_clone. upcase #=> "CaT"


Going deep into modules


Let's look one drop back and remember what modules are and how to use them, in particular, let us pay attention to the impurities and the example given there.
But what happens when mixed with our module methods? If you think that they will be included as class methods, then Ruby does not do that. To do this, you can do this:
module MyMod

def meth
puts " "
puts " ."
end

end

class
MyClass

class << self # self MyClass
include MyMod
end

end

Here the extend method is useful to us - with it the example becomes much simpler:
class MyClass
extend MyMod
end
MyClass . meth


Creating Structs


Sometimes we just need to group some data without further processing. We can create a class:
class ExtraCat

attr_accessor :name , :age , :weight

def initialize ( name, age, weight )
@name , @age , @weight = name, age, weight
end

end

lucky = ExtraCat . new ( "Lucky" , 2, 4 )
This, of course, works, but here are some repetitions. That's why the Struct class came in handy. As attr_accessor defines the necessary methods for us, and Struct defines classes that contain the same attributes. These classes are called structure templates .
ExtraCat = Struct . new ( "ExtraCat" , :name , :age , :weight )
lucky = ExtraCat . new ( "Lucky" , 2, 4 )

Epilogue


In general, I scored more for study, so that the rails again go (laid?) Forest :) Hold on, beginners, but it should be so - but then it will be easier, I promise! Yes, and finally, I built the code highlighting, it turns out, all I had to do was Windows Live Writer + Visual Studio + VSPaste + HTML Snippet + PowerGREP + regular expressions + some pen work :( But now I can make you happy with nice code, correct spelling and no longer afraid of losing articles;) And, of course, all articles of the cycle are waiting for you on the Startup Programmer blog

Source: https://habr.com/ru/post/49418/


All Articles