-
Notifications
You must be signed in to change notification settings - Fork 11
/
escrevendo-sua-propria-classe.html
223 lines (210 loc) · 19.2 KB
/
escrevendo-sua-propria-classe.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Escrevendo sua própria classe</title>
<meta name="author" content="" />
<!--- Blueprint CSS Framework -->
<link rel="stylesheet" href="css/blueprint/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/blueprint/print.css" type="text/css" media="print">
<!--[if IE]>
<link rel="stylesheet" href="css/blueprint/ie.css" type="text/css" media="screen, projection">
<![endif]-->
<!-- CodeRay syntax highlighting CSS -->
<link rel="stylesheet" href="css/coderay.css" type="text/css" />
<!-- Homepage CSS -->
<link rel="stylesheet" href="css/site.css" type="text/css" media="screen, projection" />
</head>
<body>
<div class="container">
<div class="column span-22 prepend-1 append-1 first last" id="header">
<h1 class="title"><a href="index.html" alt="voltar para o início">Tutorial de Ruby do GURU-SP</a></h1>
<hr>
</div>
<div class="column span-17 prepend-1 first">
<p class="title">Escrevendo sua própria classe</p>
<p>O paradigma procedural foi utilizado até agora para escrevermos nossos programas (note que este paradigma continua sendo utilizado em linguagens como C). Programar proceduralmente quer dizer que focamos nos passos requeridos para completar uma tarefa (de programação) sem dar muita atenção em como os dados são manipulados.</p>
<p>No paradigma de Orientação a Objetos, objetos são nossos agentes, “procuradores”, no escopo do nosso programa. Pedimos informações para os objetos. Atribuímos para eles tarefas. Dizemos para eles executarem cálculos e, em seguida, retornar o valor calculado. Juntamos uns aos outros para que trabalhem conjuntamente.</p>
<p>Quando projetamos uma classe, pensamos sobre os objetos que serão criados com base naquele tipo de classe. Pensamos sobre as coisas que o objeto <b>sabe</b> e <b>faz</b>.</p>
<p>Coisas que o objeto <b>sabe</b> sobre ele mesmo são chamadas <i>variáveis de instância</i>. Elas representam o estado do objeto (os dados: por exemplo, a quantidade e o código do produto), e podem ter valores únicos para cada objeto daquele tipo.</p>
<p>Coisas que um objeto pode <b>fazer</b> são chamados <i>métodos</i>.</p>
<blockquote>
<p>Um objeto é uma entidade que serve como um contêiner de dados e que controla o acesso a eles. Associando a um objeto um conjunto de atributos, que, essencialmente, não são mais do que variáveis que pertencem ao objeto. Também podem ser associados a um objeto um conjunto de funções que disponibilizam um meio (interface) de operarmos sobre os dados do objeto, chamados métodos. – Hal Fulton (N.T.: Tradução Livre do original)</p>
</blockquote>
<p>Um objeto é uma combinação de estados (dados) e métodos que modificam estes estados (funções).</p>
<p>Dessa forma uma classe é usada para construir um objeto. Uma classe é um molde para um objeto. Por exemplo, podemos usar uma classe Botão para fazer dezenas de botões diferentes, cada botão tendo sua própria cor, tamanho, forma, entre outras. Um objeto é uma instância de uma classe.</p>
<div class='box'>
<b>Leia cuidadosamente</b><p>Classes em Ruby são objetos de primeira classe – todas são instâncias da classe <b>Class</b>. Quando uma nova classe é definida (normalmente usando <b>class</b> Nome … <b>end</b>), um objeto do tipo <b>Class</b> é criado e é associado a uma constante (Nome, neste caso). Quando Nome.<b>new</b> é chamado para criar um novo objeto, o método de classe <b>new</b> da classe <b>Class</b> é executado primeiro para alocar memória para o objeto (através do método <b>allocate</b>) e, em seguida, o método <b>initialize</b> do novo objeto é executado. As fases de construção e inicialização de um objeto são separadas e ambas podem ser sobrescritas. A inicialização é feita pelo método de instância <b>initialize</b>, enquanto a construção é feita pelo método de classe <b>new</b>. O método <b>initialize</b> não é um construtor.</p>
</div>
<p>Vamos escrever nossa primeira classe – <b>p029dog.rb</b></p>
<div class="CodeRay">
<pre><span class="no"> 1</span> <span class="c"># p029dog.rb</span>
<span class="no"> 2</span> <span class="c"># defina a classe Cachorro</span>
<span class="no"> 3</span> <span class="r">class</span> <span class="cl">Cachorro</span>
<span class="no"> 4</span> <span class="r">def</span> <span class="fu">initialize</span>(raca, nome)
<span class="no"> 5</span> <span class="c"># Variáveis de instância</span>
<span class="no"> 6</span> <span class="iv">@raca</span> = raca
<span class="no"> 7</span> <span class="iv">@nome</span> = nome
<span class="no"> 8</span> <span class="r">end</span>
<span class="no"> 9</span>
<span class="no"><strong>10</strong></span> <span class="r">def</span> <span class="fu">late</span>
<span class="no">11</span> puts <span class="s"><span class="dl">'</span><span class="k">Au! Au!</span><span class="dl">'</span></span>
<span class="no">12</span> <span class="r">end</span>
<span class="no">13</span>
<span class="no">14</span> <span class="r">def</span> <span class="fu">mostra</span>
<span class="no">15</span> puts <span class="s"><span class="dl">"</span><span class="k">Sou da raca </span><span class="il"><span class="idl">#{</span><span class="iv">@raca</span><span class="idl">}</span></span><span class="k"> e meu nome eh </span><span class="il"><span class="idl">#{</span><span class="iv">@nome</span><span class="idl">}</span></span><span class="dl">"</span></span>
<span class="no">16</span> <span class="r">end</span>
<span class="no">17</span> <span class="r">end</span>
<span class="no">18</span>
<span class="no">19</span> <span class="c"># cria um objeto</span>
<span class="no"><strong>20</strong></span> <span class="c"># Objetos são criados na pilha</span>
<span class="no">21</span> d = <span class="co">Cachorro</span>.new(<span class="s"><span class="dl">'</span><span class="k">Labrador</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">Benzy</span><span class="dl">'</span></span>)
<span class="no">22</span>
<span class="no">23</span> <span class="c">=begin
<span class="no">24</span> Cada objeto "nasce" com certas características inatas.
<span class="no">25</span> Para ver uma lista dos métodos do objeto, você pode chamar
<span class="no">26</span> o método methods (e usar uma operação de sort para facilitar
<span class="no">27</span> a visualização). Remova o comentário e execute
<span class="no">28</span> =end</span>
<span class="no">29</span>
<span class="no"><strong>30</strong></span> <span class="c"># puts d.methods.sort</span>
<span class="no">31</span>
<span class="no">32</span> <span class="c"># Entre todos esses métodos, os métodos object_id</span>
<span class="no">33</span> <span class="c"># e respond_to são importantes.</span>
<span class="no">34</span> <span class="c"># Cada objeto no Ruby tem um id único associado ao mesmo.</span>
<span class="no">35</span>
<span class="no">36</span> puts <span class="s"><span class="dl">"</span><span class="k">O id do obj é </span><span class="il"><span class="idl">#{</span>d.object_id<span class="idl">}</span></span><span class="k">.</span><span class="dl">"</span></span>
<span class="no">37</span>
<span class="no">38</span>
<span class="no">39</span> <span class="c"># Para saber se o objeto sabe como lidar com uma mensagem que</span>
<span class="no"><strong>40</strong></span> <span class="c"># você queira enviar a ele você pode usar o método respond_to?.</span>
<span class="no">41</span> <span class="r">if</span> d.respond_to?(<span class="s"><span class="dl">"</span><span class="k">fala</span><span class="dl">"</span></span>)
<span class="no">42</span> d.fala
<span class="no">43</span> <span class="r">else</span>
<span class="no">44</span> puts <span class="s"><span class="dl">"</span><span class="k">Desculpe, o objeto nao entende a mensagem 'fala'.</span><span class="dl">"</span></span>
<span class="no">45</span> <span class="r">end</span>
<span class="no">46</span>
<span class="no">47</span> d.late
<span class="no">48</span> d.mostra
<span class="no">49</span>
<span class="no"><strong>50</strong></span> <span class="c"># fazendo d e d1 apontar para o mesmo objeto</span>
<span class="no">51</span> d1 = d
<span class="no">52</span> d1.display
<span class="no">53</span>
<span class="no">54</span> <span class="c"># tornando d uma referência nula, o que significa</span>
<span class="no">55</span> <span class="c"># que ele não se referencia a nada</span>
<span class="no">56</span> d = <span class="pc">nil</span>
<span class="no">57</span> d.display
<span class="no">58</span>
<span class="no">59</span> <span class="c"># Se eu faço</span>
<span class="no"><strong>60</strong></span> d1 = <span class="pc">nil</span>
<span class="no">61</span> <span class="c"># Então o objeto Cachorro é abandonado e elegível para ser</span>
<span class="no">62</span> <span class="c"># coletado para o lixo (GC)</span>
</pre>
</div>
<p>A saída é esta:</p>
<div class="CodeRay">
<pre><span class="no">1</span> >ruby p029dog.rb
<span class="no">2</span> O id do ocj é 22982920.
<span class="no">3</span> Desculpe, o objeto nao entende a mensagem 'fala'.
<span class="no">4</span> Au! Au!
<span class="no">5</span> Sou da raca Labrador e meu nome eh Benzy.
<span class="no">6</span> Sou da raca Labrador e meu nome eh Benzy.
<span class="no">7</span> >Exit code: 0
</pre>
</div>
<p>O método new é usado para criar um objeto da classe Cachorro. Objetos são criados na pilha (heap). A variável d é conhecida como variável de referência. Isso quer dizer que ela não contém o objeto. Contém somente alguma coisa como um ponteiro ou um endereço (de memória) para o objeto. Utilizamos o operador ponto (.) em uma variável de referência para “dizer” ao objeto: “use a coisa antes do ponto (objeto) para fazer a coisa depois do ponto (executar o método).” Por exemplo: <b>d.late</b></p>
<div class='box'>
<p><b>No framework Rails:</b><br />
Se estivermos escrevendo uma aplicação em Rails em que uma das entidades do modelo seja Cliente, então quando escrevermos o código que fazem as coisas acontecerem – um cliente acessa a área restrita de um site, atualiza seu número de telefone, adiciona um item em seu carrinho de compras – em todas essas situações estamos enviando mensagens para os objetos cliente.</p>
</div>
<p>Mesmo um objeto criado recentemente não é algo vazio. Tão breve quanto um objeto passa a existir, ele já responde a certo número de mensagens. Todo objeto “nasce” com certas habilidades inatas. Para ver uma lista desses métodos inatos, podemos chamar o método <b>methods</b> (e ainda solicitar que o resultado seja ordenado – chamando o método <b>sort</b>, – para facilitar a visualização):</p>
<div class="CodeRay">
<pre><span class="no">1</span> puts d.methods.sort
</pre>
</div>
<p>O resultado é uma lista com todas as mensagens (métodos) que este novo e recém-criado objeto possui. Entre todos estes muitos métodos, os métodos <b>object_id</b> e <b>respond_to?</b> são importantes.</p>
<p>Todo objeto em Ruby possui um identificador numérico único associado a ele. Podemos ver este identificado pedindo para o objeto mostrar seu identificador (via método <b>object_id</b>):</p>
<div class="CodeRay">
<pre><span class="no">1</span> puts <span class="s"><span class="dl">"</span><span class="k">O id do objeto é </span><span class="il"><span class="idl">#{</span>d.object_id<span class="idl">}</span></span><span class="k">.</span><span class="dl">"</span></span>
</pre>
</div>
<p>Podemos determinar antecipadamente (antes de perguntarmos alguma coisa para o objeto) se o objeto sabe como responder a mensagem que pretendemos enviar. Fazemos isso utilizando o método <b>respond_to?</b>. Esse método existe em todos os objetos; podemos questionar qualquer objeto para verificar se ele responde alguma mensagem. O método <b>respond_to?</b> normalmente aparece em conjunto com um teste lógico condicional (if).</p>
<div class="CodeRay">
<pre><span class="no">1</span> <span class="r">if</span> d.respond_to?(<span class="s"><span class="dl">"</span><span class="k">fala</span><span class="dl">"</span></span>)
<span class="no">2</span> d.fala
<span class="no">3</span> <span class="r">else</span>
<span class="no">4</span> puts <span class="s"><span class="dl">"</span><span class="k">Desculpe, o objeto nao entende a mensagem 'fala'.</span><span class="dl">"</span></span>
<span class="no">5</span> <span class="r">end</span>
</pre>
</div>
<p>As seguintes instruções:</p>
<div class="CodeRay">
<pre><span class="no">1</span> d1 = d
<span class="no">2</span> d1.display
</pre>
</div>
<p>fazem com que d e d1 apontem para o mesmo objeto.</p>
<p>Podemos perguntar para qualquer objeto de qual classe ele é membro utilizando o método <b>Object.class</b>. No programa acima, se escrevermos as seguintes instruções:</p>
<div class="CodeRay">
<pre><span class="no">1</span> d = <span class="co">Cachorro</span>.new(<span class="s"><span class="dl">'</span><span class="k">Pastor</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">Lassie</span><span class="dl">'</span></span>)
<span class="no">2</span> puts d.class.to_s
</pre>
</div>
<p>O resultado será:</p>
<div class="CodeRay">
<pre><span class="no">1</span> >ruby p029dog.rb
<span class="no">2</span> <span class="co">Cachorro</span>
<span class="no">3</span> ><span class="co">Exit</span> code: <span class="i">0</span>
</pre>
</div>
<p>O método <b>instance_of?</b> retorna verdadeiro (true) se um objeto é instância de dada classe, como no exemplo abaixo:</p>
<div class="CodeRay">
<pre><span class="no">1</span> num = <span class="i">10</span>
<span class="no">2</span> puts(num.instance_of? <span class="co">Fixnum</span>) <span class="c"># saída true</span>
</pre>
</div>
<h2>Construtores Literais</h2>
<p>Isso significa que podemos utilizar uma notação especial, ao invés de chamar <b>new</b>, para criar um novo objeto de determinada classe. As classes com construtores literais são demonstradas abaixo. Quando usamos algum desses construtores literais, fazemos que um novo objeto passe a existir.</p>
<b>Exemplos:</b><p>String – ‘hello’ or “hello”<br />
Symbol – :symbol or :“hello wrold”<br />
Array – [x, y, z]<br />
Hash – {"India" => "IN"}<br />
Range – 3..7 or 3…7</p>
<h2>Coleta de Lixo (Garbage Collection)</h2>
<p>A instrução abaixo:</p>
<p>d = nil</p>
<p>faz com que d receba uma referência para <b>nil</b>, isto significa que d não aponta para coisa alguma. Agora, se fizermos:</p>
<p>d1 = nil</p>
<p>então o objeto Cachorro é abandonado e eleito para a <b>Coleta de Lixo</b> (Garbage Collection – GC). O Ruby aloca ao menos <i>8 megabytes</i> de memória na pilha. O coletor de lixo do Ruby é do tipo de <i>marque-e-limpa</i>. O estágio de “marcação” verifica se o objeto está em uso. Se um objeto é referenciado por uma variável que pode ser utilizado no escopo atual, o objeto (e qualquer objeto dentro dele) é marcado para ser mantido. Se a variável deixa de existir e o objeto não possuir outras referências, ele não é marcado. O estágio da “limpeza” remove da memória os objetos que não foram marcados.</p>
<p>O Ruby usa um mecanismo conservador de marca-e-limpar. Não há garantia de que o objeto será liberado pelo coletor de lixo antes do programa terminar.</p>
<p>Se você colocar algo dentro de um vetor e você mantiver esse vetor ativo, ele estará <b>todo marcado</b>. Se você referenciar um objeto por uma constante ou por uma variável global, <b>ele sempre estará marcado</b>.</p>
<h2>Métodos de Classe</h2>
<p>A ideia dos métodos de classe é que você envie uma mensagem para o objeto que representa a classe ao invés de um objeto que é instância da classe. Métodos de classe cumprem esse papel. Algumas operações devem ser executadas por pela classe e não por uma instância dela. O método <b>new</b> é um excelente exemplo disso. Nós chamamos Cachorro.<b>new</b> porque até que uma instância esteja instanciada, não poderemos enviar nenhuma mensagem para o objeto. Além de que, a tarefa de gerar um novo objeto pertence à classe.</p>
<p>Não faz sentido um objeto da classe Cachorro gere outro objeto do mesmo tipo. Faz sentido, contudo, que o processo de criação de um objeto seja centralizado como uma tarefa da classe Cachorro. É vital entender que por Cachorro.new, nós podemos acessar todo o objeto da classe Cachorro, mas não suas instâncias. Os objetos do tipo cachorro (instâncias da classe Cachorro) não possuem esse método. Um objeto de classe (como Cachorro) possui seus próprios métodos, seu próprio estado, sua própria identidade e não divide essas características com suas instâncias.</p>
<p>Aqui temos um exemplo:</p>
<p><b>Cachorro#late</b> – o método de instância <b>late</b> na classe <b>Cachorro</b></p>
<p><b>Cachorro.cor</b> – o método <b>cor</b> da classe <b>Cachorro</b></p>
<p><b>Cachorro::cor</b> – outra forma de escrever o método <b>cor</b> da classe <b>Cachorro</b></p>
<p>Nos textos sobre Ruby, a notação do <i>caractere #</i> (tralha, sustenido, jogo-da-velha) é usada para indicar um método de instância, por exemplo, <b>File.chmod</b> indica o método de classe <b>chmod</b> da classe <b>File</b>, e <b>File#chmod</b> indica o método de instância que possui o mesmo nome. <b>Esta notação não faz parte da sintaxe do Ruby</b>.</p>
<p>Você aprenderá como criar seus métodos de classe nos próximos capítulos deste tutorial.</p>
<div class="pagination"><a href="ruby-method-missing.html">Ruby method missing (método faltando) ></a></div>
</div>
<div class="column span-5 append-1 last">
<p><a href="http://www.gurusp.org" title="Grupo de Usuários Ruby de SP"><img src="images/logo_guru-sp.jpg" title="Logo do GURU-SP" alt="Logo do Guru-SP" /></a></p>
<div class="box">
<p>Este material tem como base o <a href="http://www.rubylearning.com" title="Ruby Learning">tutorial do RubyLearning.com de Satish Talim</a> e foi traduzido por membros do <a href="http://www.gurusp.org" title="Grupo de Usuários Ruby de SP">GURU-SP</a> com a permissão do autor.</p>
<p class="last">Ajude o RubyLearning participando em algum dos <a href="http://www.rubylearning.org" title="cursos do Ruby Learning">cursos pagos</a> ou <a href="http://pledgie.com/campaigns/415" title="Ajude o Ruby Learning">fazendo uma doação para o projeto</a></p>
</div>
<p class="quiet"><a href="index.html" title="índice">Voltar para o índice</a></p>
<h5></h5>
<p class="incr"></p>
</div>
<div class="column span-22 prepend-1 append-1 first last" id="footer">
<hr />
<p>Tuturial de Ruby do <a href="http://www.gurusp.org" title="Grupo de Usuários Ruby de SP">GURU-SP</a>. Este site foi criado com <a href="http://webby.rubyforge.org">Webby</a></p>
</div>
</div>
</body>
</html>