Os Operadores is & as
Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 60 de 110.
Enquanto o runtimeType informa o tipo exato, o Dart fornece dois operadores que são mais práticos para verificação de tipo e conversão (casting): is e as.
O operador is verifica se um objeto é de um tipo específico e retorna um booleano. Ao contrário do runtimeType, ele também retorna true para tipos pai:
class Animal {}
class Dog extends Animal {}
void main() {
Animal pet = Dog();
print(pet is Dog); // true
print(pet is Animal); // true (Dog IS an Animal)
print(pet is String); // false
}Quando você usa is dentro de uma instrução if, o Dart promove automaticamente o tipo, permitindo que você acesse membros da subclasse sem a necessidade de conversão explícita (casting):
void handleAnimal(Animal animal) {
if (animal is Dog) {
// O Dart sabe que animal é um Dog aqui
animal.bark(); // Pode chamar métodos específicos de Dog
}
}O operador as converte explicitamente um objeto para um tipo específico. Use-o quando tiver certeza sobre o tipo:
Animal pet = Dog();
Dog myDog = pet as Dog; // Conversão para Dog
myDog.bark();Tenha cuidado com as - se a conversão falhar, ela lançará uma exceção. É por isso que combinar is com promoção de tipo é frequentemente mais seguro do que usar as diretamente. Você também pode usar is! para verificar se um objeto não é de um determinado tipo.
Desafio
FácilVamos construir um sistema de processamento de formas que utiliza os operadores is e as para identificar e trabalhar com diferentes tipos de formas. Você criará uma hierarquia de formas e escreverá funções que verificam tipos e acessam propriedades específicas de cada tipo com segurança.
Você organizará seu código em dois arquivos:
shapes.dart: Defina sua hierarquia de formas aqui:- Uma classe
Shapecom uma propriedadeString namee um construtor. Inclua um métododescribe()que imprime'$name is a shape' - Uma classe
Circleque estendeShapecom uma propriedade adicionaldouble radius. Adicione um métodogetCircleInfo()que imprime'Circle with radius: $radius' - Uma classe
Rectangleque estendeShapecom propriedades adicionaisdouble widthedouble height. Adicione um métodogetRectangleInfo()que imprime'Rectangle: $width x $height'
- Uma classe
main.dart: Importe seu arquivo de formas e crie uma funçãoprocessShape(Shape shape)que:- Primeiro chama
describe()na forma - Usa
ispara verificar se a forma é umCircle- se for, use a promoção de tipo para chamargetCircleInfo() - Usa
ispara verificar se a forma é umRectangle- se for, use o operadoraspara fazer o cast e chamargetRectangleInfo() - Usa
is!para verificar se a forma NÃO é umCirclee NÃO é umRectangle- se for o caso, imprime'Unknown shape type'
main():- Crie um
Circlechamado'Round'com raio5.0e passe-o paraprocessShape() - Imprima uma linha vazia
- Crie um
Rectanglechamado'Box'com largura4.0e altura3.0e passe-o paraprocessShape() - Imprima uma linha vazia
- Crie uma
Shapebase chamada'Mystery'e passe-a paraprocessShape()
- Primeiro chama
Este desafio demonstra ambas as abordagens: usar is com promoção automática de tipo para o Circle, e usar as para cast explícito com o Rectangle. Você também verá como is! ajuda a identificar formas que não correspondem a nenhum subtipo específico.
Saída esperada:
Round is a shape
Circle with radius: 5.0
Box is a shape
Rectangle: 4.0 x 3.0
Mystery is a shape
Unknown shape typeFolha de consulta
O operador is verifica se um objeto é de um tipo específico e retorna um booleano. Ele também retorna true para tipos pai:
class Animal {}
class Dog extends Animal {}
void main() {
Animal pet = Dog();
print(pet is Dog); // true
print(pet is Animal); // true (Dog É um Animal)
print(pet is String); // false
}Quando você usa is dentro de uma instrução if, o Dart promove automaticamente o tipo, permitindo que você acesse membros da subclasse sem a necessidade de conversão explícita (casting):
void handleAnimal(Animal animal) {
if (animal is Dog) {
// O Dart sabe que animal é um Dog aqui
animal.bark(); // Pode chamar métodos específicos de Dog
}
}O operador as converte explicitamente um objeto para um tipo específico:
Animal pet = Dog();
Dog myDog = pet as Dog; // Converte para Dog
myDog.bark();Tenha cuidado com o as - se a conversão falhar, ele lançará uma exceção. Combinar is com a promoção de tipo (type promotion) geralmente é mais seguro do que usar as diretamente.
Use is! para verificar se um objeto não é de um determinado tipo:
if (animal is! Dog) {
print("Not a dog");
}Experimente você mesmo
import 'shapes.dart';
// TODO: Crie uma função processShape(Shape shape) que:
// 1. Primeiro chame describe() na forma (shape)
// 2. Use 'is' para verificar se shape é um Circle - se sim, use a promoção de tipo para chamar getCircleInfo()
// 3. Use 'is' para verificar se shape é um Rectangle - se sim, use o operador 'as' para fazer o cast e chamar getRectangleInfo()
// 4. Use 'is!' para verificar se shape NÃO é um Circle e NÃO é um Rectangle - se sim, imprima "Unknown shape type"
void main() {
// TODO: Crie um Circle chamado 'Round' com radius 5.0 e passe-o para processShape()
// TODO: Imprima uma linha vazia
// TODO: Crie um Rectangle chamado 'Box' com width 4.0 e height 3.0 e passe-o para processShape()
// TODO: Imprima uma linha vazia
// TODO: Crie uma Shape base chamada 'Mystery' e passe-a para processShape()
}
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