Oi! Nas aulas anteriores, conhecemos as interfaces e descobrimos para que servem. O tópico de hoje ecoará o anterior. Vamos falar sobre classes abstratas em Java. Exemplos específicos de classes abstratas em Java - 1

Por que as classes são chamadas de 'abstratas'

Você provavelmente se lembra do que é 'abstração' - já falamos sobre isso. :) Se você esqueceu, não tenha medo. Lembre-se: é um princípio da POO que diz que, ao projetar classes e criar objetos, devemos identificar apenas as propriedades principais da entidade e descartar as secundárias. Por exemplo, se estamos projetando uma SchoolTeacherclasse, dificilmente precisamos de uma propriedade ' height '. De fato, essa propriedade é irrelevante para um professor. Mas se estivermos criando uma BasketballPlayerclasse, o crescimento seria uma característica importante. Então ouça. Uma classe abstrataé o mais abstrato possível — um 'branco' inacabado para um grupo de classes futuras. O espaço em branco não pode ser usado como está. É muito 'cru'. Mas descreve certo estado e comportamento geral que serão possuídos por classes futuras que herdam a classe abstrata.

Exemplos de classes Java abstratas

Considere um exemplo simples com carros:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
É assim que a classe abstrata mais simples se parece. Como você pode ver, não é nada de especial :) Por que precisaríamos disso? Em primeiro lugar, descreve nossa entidade necessária, um carro, da maneira mais abstrata possível. Há uma razão pela qual estamos usando a palavra abstract . No mundo real, não existem 'carros abstratos'. Há caminhões, carros de corrida, sedãs, cupês e SUVs. Nossa classe abstrata é simplesmente um 'plano' que usaremos mais tarde para criar classes de carros.

public class Sedan extends Car {

   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}
Isso é muito semelhante ao que falamos nas lições sobre herança. Mas nessas aulas, tínhamos uma classe Car e seus métodos não eram abstratos. Mas essa solução tem várias desvantagens que são corrigidas em classes abstratas. Em primeiro lugar, você não pode criar uma instância de uma classe abstrata :

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Os criadores do Java projetaram especificamente esse 'recurso'. Mais uma vez, como lembrete: uma classe abstrata é apenas um modelo para futuras classes 'normais' . Você não precisa de cópias do projeto, certo? E você não cria instâncias de uma classe abstrata :) Mas se a Carclasse não fosse abstrata, poderíamos facilmente criar instâncias dela:

public class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       // Some logic
   }

    public void brake() {
       // Some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Everything is fine. A car is created.
   }
}
Agora, nosso programa tem algum tipo de carro incompreensível - não é um caminhão, nem um carro de corrida, nem um sedã, e não está totalmente claro o que é. Este é o próprio 'carro abstrato' que não existe na natureza. Podemos fornecer o mesmo exemplo usando animais. Imagine se Animalclasses ( animais abstratos ). Não está claro que tipo de animal é, a que família pertence e que características possui. Seria estranho ver isso em seu programa. Não existem 'animais abstratos' na natureza. Apenas cachorros, gatos, raposas, toupeiras, etc. Classes abstratas nos livram de objetos abstratos. Eles nos dão estado e comportamento básicos. Por exemplo, todos os carros devem ter um modelo , cor e velocidade máxima , e você deve ser capaz de aplicar ogás e freio . É isso. Este é um plano abstrato geral. Em seguida, você projeta as classes necessárias. Nota: dois métodos na classe abstract também são designados como abstract , e eles não possuem nenhuma implementação. A razão é a mesma: classes abstratas não criam comportamento padrão para carros abstratos. Eles apenas indicam o que todo carro deve ser capaz de fazer. No entanto, se você precisar de um comportamento padrão, poderá implementar métodos em uma classe abstrata. Java não proíbe isso:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Gas!");
   }

   public abstract void brake();

   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
Saída do console: "Gás!" Como você pode ver, implementamos o primeiro método na classe abstrata, e não o segundo. Como resultado, o Sedancomportamento da nossa classe é dividido em duas partes: se você chamar o gas()método, a chamada 'sobe' até a Carclasse pai abstrata, mas sobrescrevemos o brake()método na Sedanclasse. Isso acaba sendo muito conveniente e flexível. Mas agora nossa classe não é tão abstrata ? Afinal, metade de seus métodos são implementados. Isso é realmente uma característica muito importante - uma classe é abstrata se pelo menos um de seus métodos for abstrato. Um dos dois métodos, ou pelo menos um dos mil métodos - não faz diferença. Podemos até implementar todos os métodos e não deixar nenhum deles abstrato. Então seria uma classe abstrata sem métodos abstratos. Em princípio, isso é possível, e o compilador não gerará erros, mas é melhor evitar: A palavra abstract perde o significado e seus colegas programadores ficarão muito surpresos :/ Ao mesmo tempo, se um método for marcado com a palavra abstract, cada classe filha deve implementá-la ou declará-la como abstract. Caso contrário, o compilador gerará um erro. Claro, cada classe pode herdar apenas uma classe abstrata, então em termos de herança não há diferença entre classes abstratas e ordinárias. Não importa se herdamos uma classe abstrata ou comum, pode haver apenas uma classe pai.

Por que Java não tem herança múltipla de classes

Já dissemos que Java não tem herança múltipla, mas ainda não exploramos o porquê. Vamos tentar fazer isso agora. O fato é que se Java tivesse herança múltipla, as classes filhas não seriam capazes de decidir qual comportamento específico deveriam escolher. Suponha que temos duas classes - Toastere NuclearBomb:

public class Toaster {


 public void on() {

       System.out.println("The toaster is on. Toast is being prepared!");
   }

   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
Como você pode ver, ambos têm um on()método. Para uma torradeira, começa a torrar. Para uma bomba nuclear, desencadeia uma explosão. Ops: / Agora imagine que você decidiu (não me pergunte por quê!) Criar algo intermediário. E assim você tem uma MysteriousDeviceaula! Este código, é claro, não funciona, e nós o fornecemos apenas como um exemplo 'mas poderia ser':

public class MysteriousDevice extends Toaster, NuclearBomb {

   public static void main(String[] args) {

       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // So what should happen here? Do we get toast or a nuclear apocalypse?
   }
}
Vamos dar uma olhada no que temos. O misterioso dispositivo herda simultaneamente a Torradeira e a Bomba Nuclear. Ambos têm on()métodos. Como resultado, se chamarmos o on()método, não fica claro qual deles deve ser invocado no MysteriousDeviceobjeto. Não há como o objeto saber. E ainda por cima: a NuclearBomb não tem um off()método, então se não acertarmos, será impossível desabilitar o dispositivo. Exemplos específicos de classes abstratas em Java - 2É justamente por causa dessa 'confusão', onde o objeto não sabe que comportamento exibir, que os criadores de Java abandonaram a herança múltipla. No entanto, você deve se lembrar de que as classes Java podem implementar várias interfaces. A propósito, em seus estudos, você já encontrou pelo menos uma classe abstrata!

public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
É seu velho amigo, a Calendarclasse. É abstrato e tem vários filhos. Um deles é GregorianCalendar. Você já o usou nas aulas sobre datas. :) Tudo parece claro o suficiente. Há apenas uma pergunta: afinal, qual é a diferença fundamental entre classes abstratas e interfaces? Por que eles adicionaram ambos ao Java em vez de apenas limitar o idioma a um? Afinal, isso teria sido inteiramente adequado. Falaremos sobre isso na próxima aula ! Até então :)