Classes Abstratas
Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 43 de 110.
Uma classe abstrata é uma classe que não pode ser instanciada diretamente. Ela serve como um modelo para outras classes, definindo uma estrutura comum que as subclasses devem seguir. Você cria uma usando a palavra-chave abstract.
abstract class Shape {
String color;
Shape(this.color);
void describe() {
print('A $color shape');
}
}
class Circle extends Shape {
double radius;
Circle(String color, this.radius) : super(color);
}
void main() {
// Shape s = Shape('red'); // Erro! Não é possível instanciar uma classe abstrata
var circle = Circle('blue', 5.0);
circle.describe(); // Uma forma azul
}Classes abstratas são úteis quando você tem um conceito que é geral demais para existir por si só. Uma "Shape" é uma ideia, mas você não pode desenhar uma forma sem saber se ela é um círculo, retângulo ou triângulo. A classe abstrata define o que todas as formas têm em comum, enquanto as subclasses concretas fornecem os detalhes específicos.
Observe que classes abstratas ainda podem ter métodos regulares com implementações (como describe()) e construtores. As subclasses herdam esses elementos exatamente como na herança normal. A principal diferença é simplesmente que você não pode criar uma instância da própria classe abstrata - você deve usar uma subclasse concreta.
Desafio
FácilVamos construir um sistema de veículos que demonstra como classes abstratas servem como modelos para tipos mais específicos. Você criará uma classe base abstrata que define o que todos os veículos têm em comum e, em seguida, a estenderá com tipos de veículos concretos.
Você organizará seu código em dois arquivos:
vehicle.dart: Defina sua hierarquia de veículos aqui:- Uma
abstract class Vehiclecom uma propriedadeString brande umaint year. Inclua um construtor que receba ambos os valores e um métododisplayInfo()que imprima[brand] ([year]) - Uma classe
Carque estendeVehiclee adiciona uma propriedadeint doors. Inclua um métodohonk()que imprimaBeep beep! - Uma classe
Motorcycleque estendeVehiclee adiciona uma propriedadebool hasSidecar. Inclua um métodorevEngine()que imprimaVroom!
- Uma
main.dart: Importe seu arquivo de veículo e demonstre como as classes abstratas funcionam:- Crie um
Carcom a marca'Toyota', ano2022e portas4 - Chame seu método
displayInfo()(herdado de Vehicle) - Imprima
Doors: [doors] - Chame seu método
honk() - Imprima uma linha vazia
- Crie uma
Motorcyclecom a marca'Harley', ano2021e hasSidecarfalse - Chame seu método
displayInfo() - Imprima
Has sidecar: [hasSidecar] - Chame seu método
revEngine()
- Crie um
Lembre-se de que você não pode criar uma instância de Vehicle diretamente, pois ela é abstrata - você deve usar uma das subclasses concretas. Tanto Car quanto Motorcycle herdam o método displayInfo() da classe pai abstrata.
Saída esperada:
Toyota (2022)
Doors: 4
Beep beep!
Harley (2021)
Has sidecar: false
Vroom!Folha de consulta
Uma classe abstrata é uma classe que não pode ser instanciada diretamente. Ela serve como um modelo para outras classes, definindo uma estrutura comum que as subclasses devem seguir. Crie uma usando a palavra-chave abstract:
abstract class Shape {
String color;
Shape(this.color);
void describe() {
print('A $color shape');
}
}
class Circle extends Shape {
double radius;
Circle(String color, this.radius) : super(color);
}
void main() {
// Shape s = Shape('red'); // Erro! Não é possível instanciar uma classe abstrata
var circle = Circle('blue', 5.0);
circle.describe(); // A blue shape
}Classes abstratas podem ter:
- Métodos regulares com implementações
- Construtores
- Propriedades
As subclasses herdam esses membros assim como na herança normal. A principal diferença é que você não pode criar uma instância da própria classe abstrata - você deve usar uma subclasse concreta.
Experimente você mesmo
import 'vehicle.dart';
void main() {
// TODO: Criar um Car com brand 'Toyota', year 2022, e doors 4
// TODO: Chamar displayInfo() no carro
// TODO: Imprimir "Doors: [doors]"
// TODO: Chamar honk() no carro
// TODO: Imprimir uma linha vazia
// TODO: Criar uma Motorcycle com brand 'Harley', year 2021, e hasSidecar false
// TODO: Chamar displayInfo() na motocicleta
// TODO: Imprimir "Has sidecar: [hasSidecar]"
// TODO: Chamar revEngine() na motocicleta
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosBibliotecas e ImportaçõesIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosVariáveis de InstânciaFundamentos de ConstrutoresRecapitulação - Calculadora Simples4Null Safety
Introdução ao Null SafetyNullable vs Non-NullableOs Operadores ? e !Palavra-chave Late e Null SafetyOperadores Null-AwareNull Safety em ClassesRecapitulação - Sistema de Perfil de Usuário7Classes Abstratas e Interfaces
Classes AbstratasMétodos AbstratosInterfaces em DartInterfaces ImplícitasImplementando vs EstendendoMúltiplas InterfacesRecapitulação - Calculadora de Formas10Coleções e Generics
Visão Geral de List, Set e MapColeções Type-SafeClasses GenéricasMétodos GenéricosRestrições de GenericsIterable e IteratorRecapitulação - Armazenamento Genérico13Conceitos Avançados de POO
Composição vs HerançaMétodos de ExtensãoClasses ChamáveisClasses Seladas (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums com Métodos16Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário2Construtores em Dart
Construtor PadrãoConstrutores NomeadosListas de InicializaçãoConstrutores ConstantesConstrutores FactoryConstrutores de RedirecionamentoRecapitulação - Shape Builder5Encapsulamento
Membros Públicos vs PrivadosA Convenção do Prefixo _Privacidade em Nível de BibliotecaAprofundamento em Getters & SettersOcultação de InformaçãoRecapitulação - Registros de Estudantes8Mixins
Introdução aos MixinsCriando MixinsUsando Múltiplos MixinsPalavra-chave on em MixinsMixin vs HerançaMixin vs InterfaceRecapitulação - Sistema Animal11Métodos Especiais
Sobrescrita de toString()Sobrescrita de hashCode & ==Interface ComparableMétodo call()Sobrescrita de noSuchMethodRecapitulação - Coleção Personalizada14Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy3Propriedades de Classe
Membros de Instância vs EstáticosCampos Final & ConstVariáveis LateMétodos e Campos EstáticosGetters e SettersRecapitulação - Gerenciador de Conta Bancária6Herança
Herança BásicaA Palavra-chave superSobrescrita de MétodoA Anotação @overrideA Palavra-chave final para ClassesConstrutores e HerançaRecapitulação - Hierarquia de Funcionários9Polimorfismo
Fundamentos do PolimorfismoPolimorfismo via InterfacesVerificação de Tipos em Tempo de ExecuçãoOs Operadores is & asPalavra-chave CovariantRecapitulação - Processador de Pagamentos12POO Assíncrona
Futures e async/awaitFundamentos de StreamsStream ControllersConstrutores AssíncronosAsync em Métodos de ClasseRecapitulação - Data Fetcher15Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Repository