-
Notifications
You must be signed in to change notification settings - Fork 11
/
heranca.html
183 lines (170 loc) · 15.7 KB
/
heranca.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
<!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>Herança</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">Herança</p>
<p>Herança é uma relação entre duas classes. Sabemos que todos gatos são mamíferos e que todos mamíferos são animais. O benefício da herança é que classes em níveis mais baixos da hierarquia obtêm as características daquelas em um nível mais alto, mas podem também adicionar características específicas a si mesmas. Se todos mamíferos respiram, então todos gatos respiram. No Ruby,<br />
uma classe pode apenas herdar de uma única outra classe. Outras linguagens suportam herança múltipla, uma funcionalidade que permite que classes herdem características de múltiplas classes, mas Ruby não suporta isso.</p>
<p>Podemos expressar esse conceito no Ruby como mostrado no programa <b>p033mammal.rb</b> abaixo:</p>
<div class="CodeRay">
<pre><span class="no"> 1</span> <span class="r">class</span> <span class="cl">Mamifero</span>
<span class="no"> 2</span> <span class="r">def</span> <span class="fu">respira</span>
<span class="no"> 3</span> puts <span class="s"><span class="dl">"</span><span class="k">inspira e expira</span><span class="dl">"</span></span>
<span class="no"> 4</span> <span class="r">end</span>
<span class="no"> 5</span> <span class="r">end</span>
<span class="no"> 6</span>
<span class="no"> 7</span> <span class="r">class</span> <span class="cl">Gato</span> < <span class="co">Mamifero</span>
<span class="no"> 8</span> <span class="r">def</span> <span class="fu">fala</span>
<span class="no"> 9</span> puts <span class="s"><span class="dl">"</span><span class="k">Miau</span><span class="dl">"</span></span>
<span class="no"><strong>10</strong></span> <span class="r">end</span>
<span class="no">11</span> <span class="r">end</span>
<span class="no">12</span>
<span class="no">13</span> rani = <span class="co">Gato</span>.new
<span class="no">14</span> rani.respira
<span class="no">15</span> rani.fala
</pre>
</div>
<p>Embora não tenhamos especificado como um Gato deve respirar, cada gato herdará este comportamento da classe Mamífero visto que Gato foi definido como uma subclasse de Mamífero (na terminologia de orientação a objetos, a classe menor é a subclasse e a classe maior é a superclasse. A subclasse é às vezes conhecida como classe derivada ou filha e a superclasse como classe pai). Portanto, do ponto de vista do programador, gatos obtêm a a habilidade de respirar de graça; após adicionarmos o método fala, nossos gatos podem respirar e falar.</p>
<p>Existirão situações em que certas propriedades da superclasse não devem ser herdadas por uma subclasse particular. Embora aves em geral saibam como voar, pinguins são uma subclasse de aves que não voam. No exemplo <b>p034bird.rb</b> abaixo, nós sobrescrevemos (override) o método voa na classe Pinguim:</p>
<div class="CodeRay">
<pre><span class="no"> 1</span> <span class="r">class</span> <span class="cl">Ave</span>
<span class="no"> 2</span> <span class="r">def</span> <span class="fu">limpase</span>
<span class="no"> 3</span> puts <span class="s"><span class="dl">"</span><span class="k">Estou limpando minhas penas.</span><span class="dl">"</span></span>
<span class="no"> 4</span> <span class="r">end</span>
<span class="no"> 5</span> <span class="r">def</span> <span class="fu">voa</span>
<span class="no"> 6</span> puts <span class="s"><span class="dl">"</span><span class="k">Estou voando.</span><span class="dl">"</span></span>
<span class="no"> 7</span> <span class="r">end</span>
<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">class</span> <span class="cl">Pinguim</span> < <span class="co">Ave</span>
<span class="no">11</span> <span class="r">def</span> <span class="fu">voa</span>
<span class="no">12</span> puts <span class="s"><span class="dl">"</span><span class="k">Desculpe. Prefiro nadar.</span><span class="dl">"</span></span>
<span class="no">13</span> <span class="r">end</span>
<span class="no">14</span> <span class="r">end</span>
<span class="no">15</span>
<span class="no">16</span> p = <span class="co">Pinguim</span>.new
<span class="no">17</span> p.limpase
<span class="no">18</span> p.voa
</pre>
</div>
<p>Ao invés de definir exaustivamente cada característica de cada nova classe, precisamos apenas adicionar ou redefinir as diferenças entre cada subclasse e de sua superclasse. Esse uso da herança é algumas vezes chamado de programação diferencial. É um dos benfícios da programação orientada a objetos.</p>
<p>Os dois programas abaixo foram tirados do <a href="http://www.rubyist.net/%7Eslagell/ruby/inheritance.html" title="em inglês">Guia do Usuário Ruby</a></p>
<p>Então, a <b>herança</b> permite que você crie uma classe que é uma versão refinada ou uma especialização de outra classe. A herança é indicada por <.</p>
<p>Aqui está outro exemplo, <b>p035inherit.rb</b>:</p>
<div class="CodeRay">
<pre><span class="no"> 1</span> <span class="r">class</span> <span class="cl">GF</span>
<span class="no"> 2</span> <span class="iv">@m</span> =<span class="i">10</span>
<span class="no"> 3</span> puts <span class="iv">@m</span>.object_id
<span class="no"> 4</span> <span class="r">def</span> <span class="fu">initialize</span>
<span class="no"> 5</span> puts <span class="s"><span class="dl">'</span><span class="k">Na classe GF</span><span class="dl">'</span></span>
<span class="no"> 6</span> <span class="r">end</span>
<span class="no"> 7</span> <span class="r">def</span> <span class="fu">gfmethod</span>
<span class="no"> 8</span> puts <span class="s"><span class="dl">'</span><span class="k">chamada de metodo de GF</span><span class="dl">'</span></span>
<span class="no"> 9</span> <span class="r">end</span>
<span class="no"><strong>10</strong></span> <span class="r">end</span>
<span class="no">11</span>
<span class="no">12</span> <span class="c"># classe F, subclasse de GF</span>
<span class="no">13</span> <span class="r">class</span> <span class="cl">F</span> < <span class="co">GF</span>
<span class="no">14</span> <span class="r">def</span> <span class="fu">initialize</span>
<span class="no">15</span> <span class="r">super</span>
<span class="no">16</span> puts <span class="s"><span class="dl">'</span><span class="k">Na classe F</span><span class="dl">'</span></span>
<span class="no">17</span> <span class="r">end</span>
<span class="no">18</span> <span class="r">end</span>
<span class="no">19</span>
<span class="no"><strong>20</strong></span> <span class="c"># classe S, subclasse de F</span>
<span class="no">21</span> <span class="r">class</span> <span class="cl">S</span> < <span class="co">F</span>
<span class="no">22</span> <span class="r">def</span> <span class="fu">initialize</span>
<span class="no">23</span> <span class="r">super</span>
<span class="no">24</span> puts <span class="iv">@m</span>
<span class="no">25</span> puts <span class="iv">@m</span>.object_id
<span class="no">26</span> puts <span class="s"><span class="dl">'</span><span class="k">Na classe S</span><span class="dl">'</span></span>
<span class="no">27</span> <span class="r">end</span>
<span class="no">28</span> <span class="r">end</span>
<span class="no">29</span>
<span class="no"><strong>30</strong></span> filho = <span class="co">S</span>.new
<span class="no">31</span> filho.gfmethod
</pre>
</div>
<p>Uma classe pode apenas herdar der uma classe de cada vez (isto é, uma classe pode herdar uma classe que herda de outra classe e que, por sua vez, herda de outra classe, mas uma única classe não pode herdar de várias classes ao mesmo tempo).</p>
<div class='box'>
<p>Existem muitas classes e módulos (mais sobre isso será explicado adiante) que vem com Ruby por padrão. Elas estão disponíveis para todos programas Ruby automaticamente; não é necessário usar o <b>require</b>. Algumas classes inclusas no Ruby são <b>Array</b>, <b>Bignum</b>, <b>Class</b>, <b>Dir</b>, <b>Exception</b>, <b>File</b>, <b>Fixnum</b>, <b>Float</b>, <b>Integer</b>, <b>IO</b>, <b>Module</b>, <b>Numeric</b>, <b>Object</b>, <b>Range</b>, <b>String</b>, <b>Thread</b>, <b>Time</b>. Alguns módulos inclusos são <b>Comparable</b>, <b>Enumerable</b>, <b>GC</b>, <b>Kernel</b>, <b>Math</b>.</p>
<p>A classe <b>Objeto</b> é a classe pai de todas as classes em Ruby. Seus métodos estão portanto disponíveis para todos os objetos ao menos que sejam explicitamente sobrescritos. No Ruby 1.9, <b>Object</b> não é mais a raiz da hierarquia de classes. Uma nova classe chamada <b>BasicObject</b> tem esse objetivo, e <b>Objeto</b> passa a ser uma subclasse de <b>BasicObject</b>. Esta é uma classe bem simples, com quase nenhum método próprio. Quando você cria uma classe no Ruby 1.9, você ainda extende <b>Object</b> ao menos que você especifique a superclasse, e, a maioria dos programadores, nunca precisará usar ou extender <b>BasicObject</b>.</p>
<p>No Ruby, <b>initialize</b> (inicializar) é um método ordinário e é herdado como qualquer outro.</p>
</div>
<div class='box'>
<p>NO RAILS: A Herança é uma das técnicas chave usadas na organização do projeto da programação e do framework.</p>
</div>
<h2>Herança e Variáveis de Instância</h2>
<p>Considere o código:</p>
<div class="CodeRay">
<pre><span class="no"> 1</span> <span class="r">class</span> <span class="cl">Cachorro</span>
<span class="no"> 2</span> <span class="r">def</span> <span class="fu">initialize</span>(raca)
<span class="no"> 3</span> <span class="iv">@raca</span> = raca
<span class="no"> 4</span> <span class="r">end</span>
<span class="no"> 5</span> <span class="r">end</span>
<span class="no"> 6</span>
<span class="no"> 7</span> <span class="r">class</span> <span class="cl">Lab</span> < <span class="co">Cachorro</span>
<span class="no"> 8</span> <span class="r">def</span> <span class="fu">initialize</span>(raca, nome)
<span class="no"> 9</span> <span class="r">super</span>(raca)
<span class="no"><strong>10</strong></span> <span class="iv">@nome</span> = nome
<span class="no">11</span> <span class="r">end</span>
<span class="no">12</span>
<span class="no">13</span> <span class="r">def</span> <span class="fu">to_s</span>
<span class="no">14</span> <span class="s"><span class="dl">"</span><span class="k">(</span><span class="dl">#</span><span class="iv">@raca</span><span class="k">, </span><span class="dl">#</span><span class="iv">@nome</span><span class="k">)</span><span class="dl">"</span></span>
<span class="no">15</span> <span class="r">end</span>
<span class="no">16</span> <span class="r">end</span>
<span class="no">17</span>
<span class="no">18</span> puts <span class="co">Lab</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>).to_s
</pre>
</div>
<p>O método <b>to_s</b> na classe Lab referencia a variável @raca da superclasse <b>Cachorro</b>. Esse código funciona como você esperaria:</p>
<div class="CodeRay">
<pre><span class="no">1</span> puts <span class="co">Lab</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>).to_s ==> (<span class="co">Labrador</span>, <span class="co">Benzy</span>)
</pre>
</div>
<p>Visto que esse código se comporta como esperado, você pode ousar dizer que todas as variáveis foram herdadas. Mas não é assim que Ruby funciona.</p>
<p>Todos objetos Ruby tem um conjunto de variáveis de instância. Essas não são definidas pelos objetos da classe – elas são simplesmente criadas quando um valor é associado as mesmas. Por variáveis de instância não serem definidas por uma classe, elas não tem relação com o mecanismo de herança.</p>
<p>No código acima, <b>Lab</b> define um método <b>initialize</b> que encadeia o método <b>initialize</b> de sua superclasse. Isto é, o método <b>super</b> passa o argumento <b>raca</b> para o método <b>initialize</b> da classe pai (<b>Cachorro</b>). O método encadeado atribui um valor para a variável <b>@raca</b>, o que faz com que essa passe a existir para uma instância particular de Lab.</p>
<p><b>super</b> é um método especial que invoca um método com mesmo nome do método atual na superclasse da classe em questão.</p>
<p>A razão para que às vezes pareça que essas variáveis de instância são herdadas está no fato das variáveis de instância serem criadas pelos primeiros métodos que atribuem valores a elas, e estes métodos são geralmente herdados ou encadeados.</p>
<p>Visto que as variáveis de instância não tem nada a ver com a herança, segue que uma variável de instância usada por uma subclasse não pode “ocultar” uma variável de instância na superclasse. Se uma subclasse usa uma variável de instância com o mesmo nome de uma variável usada em um de seus ancestrais, ela irá sobrescrever o valor da variável de seus ancestrais.</p>
<div class="pagination"><a href="sobreposicao-de-metodos.html">Sobreposição (Overriding) de Métodos ></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>