Classe abstrata em Java


274

O que é uma "classe abstrata" em Java?


35
+1 Esta pergunta é tão básica e fundamental, é um clássico para SO. Estou surpreso que não tenha sido perguntado aqui antes.
Yuval

6
-1 para o comentário de Clement (se eu pudesse); lmgtfy não é uma resposta útil. Quanto à razão, leia por exemplo, este meta.stackexchange.com/questions/5280/embrace-the-non-googlers
Jonik

26
@tuergeist. É irrelevante se for fácil para o Google, desde que isso não tenha sido solicitado antes. Além disso, quem disse que perguntas para iniciantes sobre linguagens de programação não pertencem ao SO?
Jonik

12
Uma coisa que eu gosto no SO é que você obteria uma resposta condensada, bem colocada e direta, sem nenhuma das BS usuais encontradas no resto da web ... Bem, de qualquer maneira. +1 para a pergunta!
Anders Hansson

1
SO não deveria ter apenas a cauda longa! J & J mesmo falar sobre isso em torno de podcast 56 ...
kwutchak

Respostas:


342

Uma classe abstrata é uma classe que não pode ser instanciada. Uma classe abstrata é usada criando uma subclasse herdada que pode ser instanciada. Uma classe abstrata faz algumas coisas para a subclasse herdada:

  1. Defina métodos que podem ser usados ​​pela subclasse de herança.
  2. Defina métodos abstratos que a subclasse herdada deve implementar.
  3. Forneça uma interface comum que permita que a subclasse seja intercambiada com todas as outras subclasses.

Aqui está um exemplo:

abstract public class AbstractClass
{
    abstract public void abstractMethod();
    public void implementedMethod() { System.out.print("implementedMethod()"); }
    final public void finalMethod() { System.out.print("finalMethod()"); }
}

Observe que "abstractMethod ()" não possui nenhum corpo de método. Por esse motivo, você não pode fazer o seguinte:

public class ImplementingClass extends AbstractClass
{
    // ERROR!
}

Não há método que implemente abstractMethod()! Portanto, não há como a JVM saber o que deve fazer quando obtém algo comonew ImplementingClass().abstractMethod() .

Aqui está um correto ImplementingClass.

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
}

Observe que você não precisa definir implementedMethod()ou finalMethod(). Eles já foram definidos porAbstractClass .

Aqui está outro correto ImplementingClass.

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
    public void implementedMethod() { System.out.print("Overridden!"); }
}

Nesse caso, você substituiu implementedMethod() .

No entanto, devido à finalpalavra - chave, o seguinte não é possível.

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
    public void implementedMethod() { System.out.print("Overridden!"); }
    public void finalMethod() { System.out.print("ERROR!"); }
}

Você não pode fazer isso porque a implementação de finalMethod()in AbstractClassestá marcada como a implementação final definalMethod() : nenhuma outra implementação será permitida, nunca.

Agora você também pode implementar uma classe abstrata duas vezes:

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
    public void implementedMethod() { System.out.print("Overridden!"); }
}

// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("second abstractMethod()"); }
}

Agora em algum lugar você poderia escrever outro método.

public tryItOut()
{
    ImplementingClass a = new ImplementingClass();
    AbstractClass b = new ImplementingClass();

    a.abstractMethod();    // prints "abstractMethod()"
    a.implementedMethod(); // prints "Overridden!"     <-- same
    a.finalMethod();       // prints "finalMethod()"

    b.abstractMethod();    // prints "abstractMethod()"
    b.implementedMethod(); // prints "Overridden!"     <-- same
    b.finalMethod();       // prints "finalMethod()"

    SecondImplementingClass c = new SecondImplementingClass();
    AbstractClass d = new SecondImplementingClass();

    c.abstractMethod();    // prints "second abstractMethod()"
    c.implementedMethod(); // prints "implementedMethod()"
    c.finalMethod();       // prints "finalMethod()"

    d.abstractMethod();    // prints "second abstractMethod()"
    d.implementedMethod(); // prints "implementedMethod()"
    d.finalMethod();       // prints "finalMethod()"
}

Observe que, embora tenhamos declarado bum AbstractClasstipo, ele é exibido "Overriden!". Isso ocorre porque o objeto que instanciamos era, na verdade ImplementingClass, um , e implementedMethod()é claro que ele foi substituído. (Você pode ter visto isso conhecido como polimorfismo.)

Se desejamos acessar um membro específico para uma subclasse específica, devemos converter essa subclasse primeiro:

// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();

Por fim, você não pode fazer o seguinte:

public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
    ... // implementation
}

Apenas uma classe pode ser estendida por vez. Se você precisar estender várias classes, elas deverão ser interfaces. Você consegue fazer isso:

public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
    ... // implementation
}

Aqui está um exemplo de interface:

interface InterfaceA
{
    void interfaceMethod();
}

É basicamente o mesmo que:

abstract public class InterfaceA
{
    abstract public void interfaceMethod();
}

A única diferença é que a segunda maneira não permite que o compilador saiba que na verdade é uma interface. Isso pode ser útil se você quiser que as pessoas implementem apenas sua interface e nenhuma outra. No entanto, como regra geral para iniciantes, se sua classe abstrata tiver apenas métodos abstratos, você provavelmente deve transformá-la em uma interface.

O seguinte é ilegal:

interface InterfaceB
{
    void interfaceMethod() { System.out.print("ERROR!"); }
}

Você não pode implementar métodos em uma interface. Isso significa que, se você implementar duas interfaces diferentes, os métodos diferentes nessas interfaces não poderão colidir. Como todos os métodos em uma interface são abstratos, é necessário implementar o método e, como o método é a única implementação na árvore de herança, o compilador sabe que precisa usar o método.


5
@Imagist -1 para descrição incorreta da instrução c.implementedMethod (); // imprime "managedMethod ()", imprime "Substituído!" sempre
Sachin Kumar

2
@ Saachin, perdi meia hora tentando entender por que seria impresso "managedMethod ()" e depois vi seu comentário. Algo mudou com o java ou outros simplesmente ignoraram o erro?
`` Rounak

@SachinKumar Devido à falta de resposta do autor, resolvi corrigir esse erro. CMIIW.
Mateen Ulhaq

@SachinKumar Estou um pouco atrasado para o jogo aqui, mas você diria que uma boa analogia seria uma declaração de método (mas nenhuma implementação) em um arquivo de cabeçalho C ++?
Schwaitz

5
@SachinKumar por que c.implementedMethod()imprimir "Overriden!"? SecondImplementingClassnão substitui implementedMethod().
John

75

Uma classe Java se torna abstrata nas seguintes condições:

1. Pelo menos um dos métodos está marcado como abstrato:

public abstract void myMethod()

Nesse caso, o compilador obriga a marcar toda a classe como abstrata.

2. A turma é marcada como abstrata:

abstract class MyClass

Como já foi dito: Se você possui um método abstrato, o compilador obriga a marcar toda a classe como abstrata. Mas mesmo se você não tiver um método abstrato, poderá marcar a classe como abstrata.

Uso comum:

Um uso comum de classes abstratas é fornecer um esboço de uma classe semelhante à de uma interface. Mas, diferentemente de uma interface, ela já pode fornecer funcionalidade, ou seja, algumas partes da classe são implementadas e outras são apenas descritas com uma declaração de método. ("resumo")

Uma classe abstrata não pode ser instanciada, mas você pode criar uma classe concreta com base em uma classe abstrata, que pode ser instanciada. Para fazer isso, você deve herdar da classe abstrata e substituir os métodos abstratos, ou seja, implementá-los.


1
Nitpick: a segunda 'condição' é redundante, pois você só pode declarar um método abstrato em uma classe que é explicitamente declarada como abstrata.
Stephen C

2
Concordado, o conselho não está realmente correto ou está bem escrito, está apenas formatado corretamente.
Noon Silk

Mas seu conselho de "tornar uma classe concreta" também está errado. Você não torna uma classe concreta, é ou não é, dependendo se é abstrata ou não.
Noon Silk

1
Isto é simplesmente errado. Uma classe abstrata não precisa ter nenhum método abstrato. Você pode criar uma classe abstrata sem métodos ou apenas com métodos concretos.
Jorn

1
10 anos atrasado para o jogo, mas esta é a resposta mais precisa. @ Jorn você está confuso com a resposta que eu acho. Tenho certeza de que está implícito que a abstractpalavra-chave é tudo o que é necessário para uma classe ser abstrata. Mas uma classe concreta não pode conter um abstract método . Portanto, se sua classe possui um abstractmétodo, ele deve ser declarado como uma abstractclasse para o compilador.
Rakib

24

Uma classe declarada usando a palavra-chave abstract é conhecida como abstract class. Abstração é um processo de ocultar os detalhes de implementação de dados e mostrar apenas funcionalidade ao usuário. A abstração permite que você se concentre no que o objeto faz, e não como ele faz.

Principais coisas da classe abstrata

  • Uma classe abstrata pode ou não conter métodos abstratos. Pode haver métodos não abstratos.

    Um método abstrato é um método que é declarado sem uma implementação (sem chaves e seguido por um ponto e vírgula), assim:

    ex: abstract void moveTo(double deltaX, double deltaY);

  • Se uma classe tiver pelo menos um método abstrato, essa classe deverá ser abstrata

  • Classes abstratas não podem ser instanciadas (você não tem permissão para criar objetos da classe Abstrata)

  • Para usar uma classe abstrata, você deve herdá-la de outra classe. Forneça implementações para todos os métodos abstratos nele.

  • Se você herdar uma classe abstrata, precisará fornecer implementações para todos os métodos abstratos nela.

Declarar classe abstrata A especificação da abstractpalavra-chave antes da classe durante a declaração a torna abstrata. Dê uma olhada no código abaixo:

abstract class AbstractDemo{ }

Declarar método abstrato A especificação da abstractpalavra-chave antes do método durante a declaração o torna abstrato. Dê uma olhada no código abaixo,

abstract void moveTo();//no body

Por que precisamos abstrair classes

Em um aplicativo de desenho orientado a objetos, você pode desenhar círculos, retângulos, linhas, curvas de Bezier e muitos outros objetos gráficos. Todos esses objetos têm determinados estados (por exemplo: posição, orientação, cor da linha, cor de preenchimento) e comportamentos (por exemplo:: mover, girar, redimensionar, desenhar) em comum. Alguns desses estados e comportamentos são os mesmos para todos os objetos gráficos (por exemplo: cor de preenchimento, posição e moveTo). Outros requerem implementação diferente (por exemplo: redimensionar ou desenhar). Todos os objetos gráficos devem ser capazes de desenhar ou redimensionar a si mesmos, apenas diferem em como o fazem.

Esta é uma situação perfeita para uma superclasse abstrata. Você pode tirar proveito das semelhanças e declarar todos os objetos gráficos como herdados do mesmo objeto pai abstrato (por exemplo:), GraphicObjectcomo mostrado na figura a seguir. insira a descrição da imagem aqui

Primeiro, você declara uma classe abstrata,, GraphicObjectpara fornecer variáveis ​​e métodos de membros que são totalmente compartilhados por todas as subclasses, como a posição atual e o método moveTo. GraphicObjecttambém declararam métodos abstratos, como desenhar ou redimensionar, que precisam ser implementados por todas as subclasses, mas devem ser implementados de maneiras diferentes. A GraphicObjectclasse pode ser algo como isto:

abstract class GraphicObject {

  void moveTo(int x, int y) {
    // Inside this method we have to change the position of the graphic 
    // object according to x,y     
    // This is the same in every GraphicObject. Then we can implement here. 
  }

  abstract void draw(); // But every GraphicObject drawing case is 
                        // unique, not common. Then we have to create that 
                        // case inside each class. Then create these    
                        // methods as abstract 
  abstract void resize();
}

Uso do método abstrato nas subclasses Cada subclasse não abstrata de GraphicObject, como Circlee Rectangle, deve fornecer implementações para os métodos drawe resize.

class Circle extends GraphicObject {
  void draw() {
    //Add to some implementation here
  }
  void resize() {
    //Add to some implementation here   
  }
}
class Rectangle extends GraphicObject {
  void draw() {
    //Add to some implementation here
  }
  void resize() {
    //Add to some implementation here
  }
}

Dentro do mainmétodo, você pode chamar todos os métodos como este:

public static void main(String args[]){
   GraphicObject c = new Circle();
   c.draw();
   c.resize();
   c.moveTo(4,5);   
}

Maneiras de obter abstração em Java

Existem duas maneiras de obter abstração em java

  • Classe abstrata (0 a 100%)
  • Interface (100%)

Classe abstrata com construtores, membros de dados, métodos, etc.

abstract class GraphicObject {

  GraphicObject (){
    System.out.println("GraphicObject  is created");
  }
  void moveTo(int y, int x) {
       System.out.println("Change position according to "+ x+ " and " + y);
  }
  abstract void draw();
}

class Circle extends GraphicObject {
  void draw() {
    System.out.println("Draw the Circle");
  }
}

class TestAbstract {  
 public static void main(String args[]){

   GraphicObject  grObj = new Circle ();
   grObj.draw();
   grObj.moveTo(4,6);
 }
}

Resultado:

GraphicObject  is created
Draw the Circle
Change position according to 6 and 4

Lembre-se de duas regras:

  • Se a classe tiver poucos métodos abstratos e poucos métodos concretos, declare-a como uma abstractclasse.

  • Se a classe tiver apenas métodos abstratos, declare-a como um interface.

Referências:


Por que a ordem dos parâmetros xey em moveTo é diferente no exemplo acima, no exemplo abaixo e na saída do exemplo abaixo? Se estamos tentando ilustrar a importância de conceitos como interfaces e classes abstratas, não devemos usar as mesmas assinaturas de função que as interfaces ou classes abstratas que estamos implementando ou estendendo de forma consistente?
Jonathan Rys

as duas regras
revelam

4

É uma classe que não pode ser instanciada e força a implementação de classes para, possivelmente, implementar métodos abstratos que ela descreve.


3

Simplesmente falando, você pode pensar em uma classe abstrata como uma Interface com um pouco mais de capacidade.

Você não pode instanciar uma interface, que também vale para uma classe abstrata.

Na sua interface, você pode apenas definir os cabeçalhos do método e TODOS os implementadores são forçados a implementar todos eles. Em uma classe abstrata, você também pode definir os cabeçalhos do método, mas aqui - à diferença da interface - também é possível definir o corpo (geralmente uma implementação padrão) do método. Além disso, quando outras classes estendem (observe, não implementam e, portanto, você também pode ter apenas uma classe abstrata por classe filho) sua classe abstrata, elas não são forçadas a implementar todos os seus métodos da sua classe abstrata, a menos que você tenha especificado um método abstrato ( nesse caso, funciona como para interfaces, você não pode definir o corpo do método).

public abstract class MyAbstractClass{
  public abstract void DoSomething();
}

Caso contrário, para métodos normais de uma classe abstrata, os "herdeiros" podem simplesmente usar o comportamento padrão ou substituí-lo, como de costume.

Exemplo:

public abstract class MyAbstractClass{

  public int CalculateCost(int amount){
     //do some default calculations
     //this can be overriden by subclasses if needed
  }

  //this MUST be implemented by subclasses
  public abstract void DoSomething();
}

Esta resposta não é útil se o OP não souber o que é uma interface. Como classes abstratas e interfaces estão inter-relacionadas, é altamente improvável que o OP conheça um sem conhecer o outro.
Imagist

Mas poderia ser. Pode ser que ele apenas saiba o que é uma interface e como ela funciona, e então ele se depara com classes abstratas e se pergunta por que alguém precisa delas. Não poderia ser isso?
Juri

3

Da documentação do oracle

Resumo Métodos e Classes:

Uma classe abstrata é uma classe que é declarada abstrata - pode ou não incluir métodos abstratos

Classes abstratas não podem ser instanciadas, mas podem ser subclassificadas

Um método abstrato é um método que é declarado sem uma implementação (sem chaves e seguido por um ponto e vírgula), assim:

abstract void moveTo(double deltaX, double deltaY);

Se uma classe incluir métodos abstratos, a própria classe deverá ser declarada abstrata, como em:

public abstract class GraphicObject {
   // declare fields
   // declare nonabstract methods
   abstract void draw();
}

Quando uma classe abstrata é subclassificada, a subclasse geralmente fornece implementações para todos os métodos abstratos em sua classe pai. No entanto, se isso não acontecer, a subclasse também deve ser declarada abstrata .

Desde abstract classese interfacesrelacionados, dê uma olhada nas perguntas abaixo SE:

Qual é a diferença entre uma interface e uma classe abstrata?

Como devo ter explicado a diferença entre uma interface e uma classe abstrata?


3

Obtenha suas respostas aqui:

Classe abstrata vs Interface em Java

Uma classe abstrata pode ter um método final?

Entre - essas são as perguntas que você fez recentemente. Pense em uma nova pergunta para construir reputação ...

Editar:

Acabei de perceber que os cartazes desta e das perguntas referenciadas têm o mesmo ou pelo menos um nome semelhante, mas o ID do usuário é sempre diferente. Então, também, há um problema técnico, que o keyur tem problemas para fazer login novamente e encontrar as respostas para suas perguntas ou esse é um tipo de jogo para entreter a comunidade SO;)


E é por isso que eu verifiquei o 'wiki da comunidade' - não se deve aumentar a reputação reagindo a essas perguntas;)
Andreas Dolk

1

Pouca adição a todos esses posts.

Às vezes, você pode declarar uma classe e ainda não sabe como definir todos os métodos que pertencem a essa classe. Por exemplo, você pode declarar uma classe chamada Writer e incluir nela um método membro chamado write () . No entanto, você não sabe codificar write () porque é diferente para cada tipo de dispositivo Writer. Obviamente, você planeja lidar com isso derivando subclasses de Writer, como Impressora, Disco, Rede e Console.


1

Uma classe abstrata não pode ser instanciada diretamente, mas deve ser derivada para ser utilizável. Uma classe DEVE ser abstrata se contiver métodos abstratos: diretamente

abstract class Foo {
    abstract void someMethod();
}

ou indiretamente

interface IFoo {
    void someMethod();
}

abstract class Foo2 implements IFoo {
}

No entanto, uma classe pode ser abstrata sem conter métodos abstratos. É uma maneira de impedir a instanciação direta, por exemplo

abstract class Foo3 {
}

class Bar extends Foo3 {

}

Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!

O último estilo de classes abstratas pode ser usado para criar classes "semelhantes a interfaces". Diferentemente das interfaces, uma classe abstrata pode conter métodos não abstratos e variáveis ​​de instância. Você pode usar isso para fornecer alguma funcionalidade básica para estender classes.

Outro padrão frequente é implementar a funcionalidade principal na classe abstrata e definir parte do algoritmo em um método abstrato a ser implementado por uma classe estendida. Exemplo estúpido:

abstract class Processor {
    protected abstract int[] filterInput(int[] unfiltered);

    public int process(int[] values) {
        int[] filtered = filterInput(values);
        // do something with filtered input
    }
}

class EvenValues extends Processor {
    protected int[] filterInput(int[] unfiltered) {
        // remove odd numbers
    }
}

class OddValues extends Processor {
    protected int[] filterInput(int[] unfiltered) {
        // remove even numbers
    }
}

1

Solução - classe base (resumo)

public abstract class Place {

String Name;
String Postcode;
String County;
String Area;

Place () {

        }

public static Place make(String Incoming) {
        if (Incoming.length() < 61) return (null);

        String Name = (Incoming.substring(4,26)).trim();
        String County = (Incoming.substring(27,48)).trim();
        String Postcode = (Incoming.substring(48,61)).trim();
        String Area = (Incoming.substring(61)).trim();

        Place created;
        if (Name.equalsIgnoreCase(Area)) {
                created = new Area(Area,County,Postcode);
        } else {
                created = new District(Name,County,Postcode,Area);
        }
        return (created);
        }

public String getName() {
        return (Name);
        }

public String getPostcode() {
        return (Postcode);
        }

public String getCounty() {
        return (County);
        }

public abstract String getArea();

}

1
tente formatar todo o código como código e adicione algumas explicações. No momento, isso dificilmente pode ser considerado uma resposta.
NomeN 24/08/09

3
até e a menos que você não tenha explicado seu código. Você seria considerado um criador de respostas ruins. Então, por favor, explique aqui
devsda

0

Uma classe abstrata é uma classe que é declarada abstrata - pode ou não incluir métodos abstratos. Classes abstratas não podem ser instanciadas, mas podem ser subclassificadas.

Em outras palavras, uma classe declarada com a palavra-chave abstract é conhecida como classe abstrata em java. Pode ter métodos abstratos (método sem corpo) e não abstratos (método com corpo).

Nota importante: - Classes abstratas não podem ser usadas para instanciar objetos, elas podem ser usadas para criar referências a objetos, porque a abordagem de Java ao polimorfismo em tempo de execução é implementada através do uso de referências de superclasse. Portanto, deve ser possível criar uma referência a uma classe abstrata para que possa ser usada para apontar para um objeto de subclasse. Você verá esse recurso no exemplo abaixo

abstract class Bike{  
  abstract void run();  
}  

class Honda4 extends Bike{  
    void run(){
        System.out.println("running safely..");
    }  

    public static void main(String args[]){  
       Bike obj = new Honda4();  
       obj.run();  
    }  
} 

0

Uma classe abstrata é aquela que não está totalmente implementada, mas fornece uma espécie de blueprint para subclasses. Pode ser parcialmente implementado, pois contém métodos concretos totalmente definidos, mas também pode conter métodos abstratos. Estes são métodos com uma assinatura, mas sem corpo de método. Qualquer subclasse deve definir um corpo para cada método abstrato, caso contrário, também deve ser declarado abstrato. Como as classes abstratas não podem ser instanciadas, elas devem ser estendidas por pelo menos uma subclasse para serem utilizadas. Pense na classe abstrata como a classe genérica, e as subclasses existem para preencher as informações ausentes.


0

Classe que pode ter métodos concretos e não concretos, isto é, com e sem corpo.

  1. Métodos sem implementação devem conter a palavra-chave 'abstract'.
  2. A classe abstrata não pode ser instanciada.

-1

Não faz nada, apenas forneça um modelo comum que será compartilhado para sua subclasse

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.