• Nenhum resultado encontrado

5. Hierarquia de Classes, Herança a e Polimorfismo

N/A
N/A
Protected

Academic year: 2021

Share "5. Hierarquia de Classes, Herança a e Polimorfismo"

Copied!
37
0
0

Texto

(1)

© ELFS 116

• Como vimos, na POO devemos construir classes para modelar os dados de um programa. Vimos, por exemplo, que para um programa de simulação do tráfego em uma rodovia, podemos imaginar uma classe Veiculo.

• Ao construir a classe Veiculo estamos imaginando um veículo qualquer.

Pode acontecer que, para o programa, seja necessário trabalhar com tipos especializados de veículos, como caminhão, carro de passeio ou

motocicleta.

• Neste caso, deveremos construir novas classes para os tipos de veículos necessários. Para construir essas novas classes, no entanto, podemos

tomar a classe Veiculo como base. Assim, as novas classes serão subclasses da classe Veiculo, o que tem sentido, pois um caminhão, um carro de

passeio ou uma motocicleta, continua sendo um veículo.

• Este mecanismo, disponível na POO, de construção de classes tendo como base uma outra classe permite construir uma hierarquia de classes.

Veiculo

double velocidade

int posicao

+ void aumentarVelocidade() + void diminuirVelocidade() + void atualizarPosicao()

(2)

• Portanto, numa hierarquia de classes, tem-se uma classe mais geral

(denominada superclasse) que serve de base para a construção de classes mais específicas (denominadas subclasses).

• O relacionamento existente entre uma subclasse e sua superclasse é do tipo

"é um(a)". Exemplo: Carro é um Veiculo.

Veiculo

# double velocidade

# int posicao

+ void aumentarVelocidade() + void diminuirVelocidade() + void atualizarPosicao()

Motocicleta

boolean pagaPedagio Carro

int numPassageiros + void atualizarPosicao() Caminhao

double capacidade

int numEixos + void incluirCarga() + void retirarCarga()

Note que os campos da superclasse devem ser

protected (e não private) para serem herdados pelas subclasses.

(3)

© ELFS 118

• Em Java, uma classe pode herdar apenas de uma superclasse, o que é

conhecido como estrutura de herança simples (ou seja, não existe herança múltipla). Mais à frente veremos que com interfaces podemos implementar mecanismos de herança múltipla.

• Definição de classe tendo como base uma outra classe:

• O modificador estabelece o nível de acesso à classe. Classes só podem ser definidas no nível public (acesso total) ou pacote (ausência do modificador).

[<modificador>] class <nome_classe> [extends <nome_superclasse>]

{

[<declaração_atributos>]

[<declaração_construtores>]

[<declaração_métodos>]

}

Modificador Classe Pacote Subclasse Todas

public 9 9 9 9

(package) 9 9

public class Carro extends Veiculo { private int numPassageiros;

} ...

Exemplo:

(4)

• Os membros de uma classe (campos e métodos) podem ser definidos com os seguintes níveis de acesso:

public - os membros públicos de uma superclasse são acessíveis a suas subclasses e a qualquer classe usuária dessa superclasse.

protected - os membros protegidos de uma superclasse podem ser acessados apenas por métodos da superclasse, por métodos de

subclasses e por métodos de outras classes do mesmo pacote.

private - os membros privados de uma superclasse são acessíveis apenas aos métodos dessa superclasse.

A classe Object

• Todas as classes herdam, em última instância, da classe Object. A classe Object possui diversos métodos que podem ser reutilizados pelas classes de

Modificador Classe Pacote Subclasse Todas

public 9 9 9 9

protected 9 9 9

(package) 9 9

private 9

(5)

© ELFS 120

Sobreposição ( overriding ) e sobrecarga ( overloading ) de métodos

• Com a estrutura de herança, uma subclasse herda o comportamento (métodos) de sua superclasse. A subclasse, no entanto, pode alterar o comportamento herdado. A isto, dá-se o nome de sobreposição (ou redefinição) de métodos.

• Para a sobreposição, o método da subclasse deve ser declarado exatamente com o mesmo nome, tipo de retorno e lista de parâmetros (inclusive a

ordem). O modificador de acesso pode mudar, mas o método na subclasse não pode ser menos acessível do que o método da superclasse.

• Como vimos anteriormente, os métodos podem ser sobrecarregados. Em uma subclasse, haverá a sobrecarga de métodos se métodos herdados da superclasse forem também definidos (com o mesmo nome mas com uma lista de parâmetros diferente) na subclasse.

• A palavra-chave super pode ser utilizada em uma subclasse para acessar os membros da superclasse (ou métodos de níveis acima na hierarquia).

(6)

Uma das grandes vantagens da POO é permitir que uma mesma

variável possa referenciar diferentes objetos de uma hierarquia de

classes.

Cada objeto tem sua própria forma e comportamento (que são definidos quando o objeto é construído).

Como a variável pode referenciar objetos diferentes, essa variável

terá diferentes formas e comportamentos. A esta característica dá-se

o nome de polimorfismo.

(7)

© ELFS 122

• Exemplo:

Midia

# int codigo

# float preco

+String getDetalhes()

DVD

# String autor

+String getDetalhes()

CD

# int numMusicas +String getDetalhes()

(8)

• Exemplo: public class Midia {

protected int codigo;

protected float preco;

public String getDetalhes()

{ return codigo + ": " + preco; } } public class DVD extends Midia

{

protected String autor;

public String getDetalhes() {

return super.getDetalhes() +

" - " + autor;

}

} public class CD extends Midia {

protected int numMusicas;

public String getDetalhes() {

return super.getDetalhes() +

(9)

© ELFS 124

Midia m = new Midia();

m.getDetalhes(); // será chamado o método da superclasse m = new DVD();

m.getDetalhes(); // será chamado o método da subclasse

• Considere que uma classe usuária das classes Midia e DVD declara:

O método a ser chamado é definido em tempo de execução (runtime). A isso dá-se o nome de ligação dinâmica de método. Daí vem o polimorfismo.

Observe que quando a variável m aponta para o objeto DVD, a partir de m tem-se acesso aos campos e métodos (herdados) da superclasse

(Midia). No entanto, para os métodos de Midia que sofreram sobreposição em DVD, o acesso é feito aos métodos da subclasse.

n o

Stack Heap

m Midia

o

DVD

n

(10)

Exercício:

Implemente as classes da seguinte hierarquia: Complexo, Real e

Inteiro, onde Complexo

é a superclasse da hierarquia.

Considere que cada classe deve ter seus construtores (padrão e com parâmetros) e os métodos:

getClasse()

(que retorna o nome da classe) e,

getValor()

(que retorna como um objeto desta classe deve ser exibido).

Escreva um programa que cria e exibe objetos de cada uma dessas

classes.

(11)

© ELFS 126

• Exemplo:

Complexo

# int parte1

# int parte2

+String getClasse() +String getValor() +String toString()

Real

+String getClasse() +String getValor()

Inteiro

+String getClasse() +String getValor()

(12)

public class Complexo {

protected int parte1;

protected int parte2;

public Complexo() {

parte1 = 0;

parte2 = 0;

}

Complexo.java

Vamos considerar que as partes real e imaginária de um número

complexo são valores inteiros.

(13)

© ELFS 128

public Complexo(int r, int i) {

parte1 = r;

parte2 = i;

}

public String getClasse() {

return "Complexo";

}

public String getValor() {

return "(" + parte1 + ", " + parte2 + ")";

}

public String toString() {

return "Sou um " + getClasse() +

". Meu valor = " + getValor();

}

} O método toString() será herdado

pelas demais classes da hierarquia.

(14)

public class Real extends Complexo {

public Real() {

parte1 = 0;

parte2 = 0;

}

public Real(int i, int f) {

parte1 = i;

parte2 = f;

}

public String getClasse() {

return "Real";

}

public String getValor() {

Real.java

Neste caso, os campos parte1 e parte2 herdados da classe Complexo são

interpretados como as partes inteira e fracionária de um número real.

(15)

© ELFS 130

public class Inteiro extends Real {

public Inteiro() {

parte1 = 0;

}

public Inteiro(int i) {

parte1 = i;

}

public String getClasse() {

return "Inteiro";

}

public String getValor() {

return Integer.toString(parte1);

} }

Inteiro.java

(16)

public class TestaHierarquia {

public static void main(String arg[]) {

Complexo c = new Complexo(7,3);

System.out.println(c);

Real r = new Real(7,3);

System.out.println(r);

Inteiro i = new Inteiro(7);

System.out.println(i);

} }

TestaHierarquia.java

Neste caso, a saída será:

(17)

© ELFS 132

# String nome

# String especie

Cachorro Gato

+ Bicho()

+ Bicho(String n, String e)

+ void setBicho(String n, String e) + void setNome(String n)

+ void setEspecie(String e) + String getNome()

+ String getEspecie() + void emitirSom() + String toString()

# int forcaLatido + Cachorro()

+ Cachorro(String n, String e, int f)

+ void setCachorro(String n, String e, int f) + void setForcaLatido(int f)

+ int getForcaLatido() + void emitirSom() + String toString()

# int forcaMiado + Gato()

+ Gato(String n, String e, int f)

+ void setGato(String n, String e, int f) + void setForcaMiado(int f)

+ int getForcaMiado() + void emitirSom() + String toString()

* *

*

(18)

Argumentos Polimórficos

• Imagine que a classe CD foi definida como uma nova subclasse de Midia e que as classes CD e DVD contêm um método calcularPreco(). É importante que esse método seja definido em cada subclasse, pois no cálculo do preço deve-se levar em consideração o tipo de mídia.

• A questão que se coloca é a seguinte:

Em vez de incluir o método calcularPreco() em cada uma das subclasses, seria possível incluí-lo apenas na superclasse?

Midia

CD DVD

(19)

• Como CD e DVD são subclasses de Midia, objetos das classes CD ou DVD podem ser passados como argumentos para um método que espera como parâmetro um objeto da classe Midia (afinal, todo CD é uma Midia e todo DVD é uma Midia).

• Na chamada, o parâmetro passado para esse método poderá ser um objeto da classe Midia ou um objeto de uma de suas subclasses (CD ou DVD).

© ELFS 134

public void calcularPreco(Midia m) {

if (m instanceof CD) preco = 15.00;

else

if (m instanceof DVD) preco = 30.00;

else

preco = 2.00;

}

Notar que para determinar a classe do objeto recebido como parâmetro, utiliza-se o operador instanceof.

(20)

public class Midia {

protected int codigo;

protected double preco;

public Midia() {

codigo = 0;

preco = 0.0;

}

public Midia(int c) {

codigo = c;

preco = 0.0;

}

public String getDetalhes() {

return "Código = " + codigo + ", Preço = " + preco;

}

public void calcularPreco(Midia m)

Midia.java

(21)

© ELFS 136

public class CD extends Midia {

protected int numMusicas;

public CD() {

numMusicas = 0;

}

public CD(int n) {

numMusicas = n;

}

public int getNumMusicas() {

return numMusicas;

}

public String getDetalhes() {

return super.getDetalhes() +

" (" + getNumMusicas() + " músicas)";

} }

CD.java

(22)

public class DVD extends Midia {

protected int categoria;

public DVD() {

categoria = 0;

}

public DVD(int c) {

categoria = c;

}

public int getCategoria() {

return categoria;

}

public String getDetalhes() {

return super.getDetalhes() +

" (categoria = " + getCategoria() + ")";

}

DVD.java

(23)

© ELFS 138

public class TestaMidia {

public static void main(String arg[]) {

Midia m = new Midia(987);

System.out.println("Classe do objeto: " + m.getClass());

System.out.println("Detalhes do objeto: " + m.getDetalhes());

m.calcularPreco(m);

System.out.println("Detalhes do objeto: " + m.getDetalhes());

CD c = new CD(10);

System.out.println("Classe do objeto: " + c.getClass());

System.out.println("Detalhes do objeto: " + c.getDetalhes());

c.calcularPreco(c);

System.out.println("Detalhes do objeto: " + c.getDetalhes());

DVD d = new DVD(1);

System.out.println("Classe do objeto: " + d.getClass());

System.out.println("Detalhes do objeto: " + d.getDetalhes());

d.calcularPreco(d);

System.out.println("Detalhes do objeto: " + d.getDetalhes());

} }

TestaMidia.java

(24)

Duas questões importantes sobre o programa TestaMidia:

• A saída do programa será:

Note que na criação dos objetos das classes CD e DVD, o método padrão da superclasse é chamado automaticamente (atribuindo os valores zero para os campos codigo e preco).

• Observe as linhas:

Classe do objeto: class Midia

Detalhes do objeto: Código = 987, Preço = 0.0 Detalhes do objeto: Código = 987, Preço = 2.0 Classe do objeto: class CD

Detalhes do objeto: Código = 0, Preço = 0.0 (10 músicas) Detalhes do objeto: Código = 0, Preço = 15.0 (10 músicas) Classe do objeto: class DVD

Detalhes do objeto: Código = 0, Preço = 0.0 (categoria = 1) Detalhes do objeto: Código = 0, Preço = 30.0 (categoria = 1)

m.calcularPreco(m);

c.calcularPreco(c);

d.calcularPreco(d);

O método deve ser chamado por um objeto. Mas, o método requer um parâmetro que, no caso, é o mesmo objeto que chama o método.

(25)

© ELFS 140

• Isto é possível, usando-se a palavra reservada this.

• A palavra this usada no corpo de um método corresponde ao objeto que chamou o método. Desta forma, o método calcularPreco() pode ser escrito como:

e, com isso, o método não precisa de parâmetro e as linhas do programa TestaMidia poderão ser escritas como:

public void calcularPreco() {

if (this instanceof CD) preco = 15.00;

else

if (this instanceof DVD) preco = 30.00;

else

preco = 2.00;

}

m.calcularPreco();

c.calcularPreco();

d.calcularPreco();

(26)

Conversão de objetos

• A conversão de objetos é necessária quando uma variável de uma classe aponta para um objeto de outra classe. Para a conversão deve-se observar:

• Conversões para cima em uma hierarquia (converter um objeto de uma subclasse para um objeto da superclasse) são feitas automaticamente.

• Conversões para baixo em uma hierarquia (converter um objeto da superclasse para um objeto da subclasse) devem ser indicadas

explicitamente (cast ).

• Se o compilador permitir a conversão, o tipo de objeto será verificado em tempo de execução.

Exemplo:

Midia

CD DVD

Midia m = new Midia();

CD c = new CD();

DVD d = new DVD();

m = c; // conversão automática

(27)

© ELFS 142

Construtores e Herança

• Um construtor de uma subclasse pode chamar explicitamente um construtor de sua superclasse utilizando o método super(). Neste caso, a chamada ao método super() deve ser a primeira linha do construtor da subclasse. A partir dos argumentos passados a esse método, a JVM saberá qual construtor da superclasse deve ser chamado.

• Se no construtor da subclasse nenhuma chamada a this() (construtor da própria classe) ou a super() for feita, o compilador incluirá automaticamente uma chamada a super(). Neste caso, uma chamada ao construtor sem

parâmetros da superclasse será realizada. Se a superclasse não tiver um construtor sem parâmetros, um erro será gerado pelo compilador.

• Se na subclasse não existir um construtor, a chamada super() também será inserida no construtor padrão (inserido automaticamente pelo compilador).

• Resumo: ou a subclasse não tem construtor (super() implícito é adicionado), ou o construtor da subclasse chama explicitamente um construtor da

superclasse. Para não haver erros, ou a superclasse tem um construtor sem parâmetros ou nenhum construtor.

• Objetivo: garantir que um objeto da classe Object seja instanciado.

(28)

Construtores, Herança e a Classe Object

public class Object {

public Object() {}

}

public class Midia extends Object {

protected int codigo;

protected double preco;

public Midia (int c, double p) {

// chamada implicita a super() codigo = c;

preco = p;

}

public Midia (int c) {

this(c, 0.0);

public class DVD extends Midia {

protected String autor;

public DVD (String a) {

super(10);

IMPORTANTE:

this() corresponde a uma chamada ao construtor da própria classe.

super() corresponde a uma chamada ao construtor da superclasse.

(29)

© ELFS 144

Exemplo:

public class Ponto1 {

protected int x, y; // coordenadas do ponto // Construtores

public Ponto1() {

x = 0;

y = 0;

}

public Ponto1(int a, int b) {

x = a;

y = b;

}

public int getX() { return x; } public int getY() { return y; } public String toString()

{

return "[" + x + ", " + y + "]";

} }

Note que a definição da classe Ponto1 não utiliza a palavra-chave extends. Se a palavra extends não for usada, a linguagem Java considera implicitamente a classe Object como superclasse.

O construtor de uma classe chama explícita ou

implicitamente o construtor da superclasse. Nesse caso, haverá uma chamada implícita ao construtor padrão de Object.

Aqui também haverá uma chamada (implícita) ao construtor padrão de Object.

Ponto1.java

(30)

public class Circulo1 extends Ponto1 {

protected double raio;

public Circulo1() {

raio = 0;

}

public Circulo1(double r, int a, int b) {

super(a, b); // chama construtor da superclasse raio = (r >= 0 ? r : 0.0);

}

public double getRaio() { return raio; } public double area()

{

return Math.PI * Math.pow(raio,2);

}

public String toString() {

No construtor-padrão de Circulo1 haverá uma chamada implícita ao construtor de Ponto1 (note que se a classe Ponto1 tivesse apenas o construtor com

parâmetros, haveria um erro de

compilação nessa linha do programa).

Note que para o outro construtor de Circulo1 a chamada ao construtor da superclasse é explícita.

Circulo1.java

O método toString() da classe Circulo1 sobrescreve (override) o método toString() da classe Ponto1, da mesma forma que o método

toString() da classe Ponto1

sobrescreve o método toString() da classe Object.

(31)

© ELFS 146

import java.text.DecimalFormat;

public class TestaPC1 {

public static void main(String args[]) {

Ponto1 pRef, p;

Circulo1 cRef, c;

String sai;

p = new Ponto1(30, 50);

c = new Circulo1(2.5, 120, 90);

sai = "Ponto p: " + p + "\nCirculo c: " + c;

pRef = c;

sai += "\n\nCirculo c (via pRef): " + pRef;

cRef = (Circulo1) pRef;

sai += "\n\nCirculo c (via cRef): " + cRef;

DecimalFormat doisDigitos = new DecimalFormat("0.00");

sai += "\nArea de c (via cRef): " + doisDigitos.format(cRef.area());

if (p instanceof Circulo1) {

cRef = (Circulo1) p;

sai += "\n\nSucesso na coerção";

} else

sai += "\n\np não se refere a um circulo";

System.out.println(sai);

} }

Note que:

pRef = c é possível (pois

Circulo1 é subclasse de Ponto1) mas,

cRef = (Circulo1) pRef necessita de cast (coerção).

(32)

• Para conferir a saída:

Ponto p: [30, 50]

Circulo c: Centro = [ 120, 90]; Raio = 2.5

Circulo c (via pRef): Centro = [ 120, 90]; Raio = 2.5 Circulo c (via cRef): Centro = [ 120, 90]; Raio = 2.5 Area de c (via cRef): 19,63

p não se refere a um circulo

(33)

© ELFS 148

Construtores e Finalizadores em Subclasses

• Em Java, quando um objeto não é mais utilizado (isto é, quando não há referências para o objeto), ele é marcado como lixo. O coletor de lixo é executado de tempos em tempos para recuperar a memória consumida pelos objetos marcados como lixo.

• Cada classe pode incluir um método finalizador (finalize) que "termina a

limpeza" em cada objeto da classe antes da memória consumida pelo objeto ser coletada. A chamada ao método finalize não garante que o coletor de lixo será chamado imediatamente, pois é a JVM quem decide quando o coletor de lixo é chamado.

• Quando um objeto de uma subclasse é criado, o construtor da superclasse é chamado (implícita ou explicitamente). Isso é importante para fazer as

inicializações necessárias nos campos da superclasse, herdadas pelo objeto da subclasse.

• Para a finalização, a última instrução de um método finalize deve ser

super.finalize(), para assegurar que o método finalize da superclasse seja chamado e que todas as partes de um objeto estejam finalizadas

adequadamente quando o coletor de lixo coletar esse objeto.

(34)

Exemplo: Ordem em que os construtores e finalizadores são chamados.

public class Ponto2

{ protected int x, y; // coordenadas do ponto

public Ponto2() { x = 0;

y = 0;

System.out.println("Ponto2 construido: " + this);

}public Ponto2( int a, int b ) { x = a;

y = b;

System.out.println("Ponto2 construido: " + this);

}

protected void finalize()

{ System.out.println("Ponto2 finalizado: " + this);

}

public String toString() O método finalize() de uma classe deve Ponto2.java

A variável this é uma referência ao objeto que chamou o método.

(35)

© ELFS 150

public class Circulo2 extends Ponto2 {

protected double raio;

public Circulo2() {

raio = 0;

System.out.println("Circulo2 construido: " + this);

}

public Circulo2(double r, int a, int b) {

super(a, b); // chama construtor da superclasse raio = r;

System.out.println("Circulo2 construido: " + this);

}

protected void finalize() {

System.out.println("Circulo2 finalizado: " + this);

super.finalize();

}

public String toString() {

return "Centro = " + super.toString() + "; Raio = " + raio;

} }

Note que aqui há uma chamada implícita ao construtor da superclasse.

Note que a ausência da referência super

causaria uma recursão infinita, porque o método da subclasse estaria chamando a si próprio.

Circulo2.java

(36)

public class TestaPC2 {

public static void main(String args[]) {

Ponto2 p1;

Circulo2 c1, c2;

p1 = new Ponto2(3, 4);

c1 = new Circulo2(4.5, 72, 29);

c2 = new Circulo2(10, 5, 5);

c1 = null; // marca para coleta de lixo c2 = null;

p1 = null;

System.gc(); // chama o coletor de lixo }

}

Note pela saída do programa que, na construção dos objetos c1 e c2, o polimorfismo faz com que o método toString() executado seja o da classe Circulo2 pois são objetos Circulo2 que estão sendo criados.

Note que quando toString() é chamado a partir do construtor

Ponto2, o valor para o campo raio é zero porque raio ainda não foi

inicializado no construtor Circulo2.

TestaPC2.java

Ponto2 construido: [3, 4]

Ponto2 construido: Centro = [72, 29]; Raio = 0.0 Circulo2 construido: Centro = [72, 29]; Raio = 4.5 Ponto2 construido: Centro = [5, 5]; Raio = 0.0 Circulo2 construido: Centro = [5, 5]; Raio = 10.0 Circulo2 finalizado: Centro = [5, 5]; Raio = 10.0 Ponto2 finalizado: Centro = [5, 5]; Raio = 10.0

Observe que a ordem de finalização é contrária à da construção, pois o método finalize() da superclasse é a última instrução a ser executada no método finalize() da

subclasse. Observe também que não há garantia da ordem em

(37)

© ELFS 152

A palavra-chave final

• Algumas vezes pode ser interessante que um elemento de um programa (classe, campo ou método) não possa ser modificado. Nestes casos, a palavra-chave final deve ser usada.

• Classe final: uma classe especificada como final não pode ter subclasses. A classe String é final: garante-se que essa classe não será alterada.

• Método final: um método definido como final não pode ser redefinidos.

Métodos são definidos como final quando sua implementação não puder ser alterada por alguma razão. Métodos declarados como static ou como

private são implicitamente final. Todos os métodos de uma classe final são implicitamente final.

• Campo final: um campo definido como final não pode ser modificado, ou seja, é uma constante. Uma vez atribuído um valor ao campo este valor não pode ser alterado. Uma classe pode ter um campo final que não é inicializado na definição e sim em um construtor, mas uma vez que a atribuição seja feita, o valor não pode mudar.

Referências

Documentos relacionados

Este comportamento era feito num recipiente colocado no meio da área de forrageamento, a formiga subia no recipiente, inclinava-se para alcançar o líquido, abria as

aumento do número de casos de uma determinada doença acima do esperado em condições normais, numa área específica e num determinado período de

Este artigo aborda o resultado, comparativamente, em três empresas quanto à repetição ou não da mesma parte do corpo envolvida em acidente típico após realização de treinamentos

O Relatório de Atividades 2020 da Escola Superior de Turismo e Tecnologia do Mar do Politécnico de Leiria (adiante designada por ESTM), reporta-se ao ano civil e pretende ser um

ASSEMBLEIA SETORIAL VIRTUAL DE APOSENTADOS, a ser realizada no dia 09 de abril de 2021, com primeira convocação às 14:00 horas, com a presença de 2/3.. (dois terços) dos filiados,

Comparativamente com a informação processada na segunda fase do estudo, a informação constante do conteúdo dos anúncios não obedece a qualquer estrutura prefixada, tendo a entidade

10.9 - Em caso de não aceitação, quando do recebimento provisório fica o FORNECEDOR obrigado a substituir os produtos, sem custos para o ÓRGÃO GERENCIADOR, no prazo de

São Paulo 2015; 27(2): 118- 25, maio-ago ISSN 1983-5183 Martins JS Campos BM Nahás-Scocate ACR Fuziy A Freitas CF Costa ALF Avaliação do volume do disco articular da ATM por meio