Polimorfismo
Polimorfismo
Transformação para cima
Animal animal = new Bird();
Como este formulário,A referência da classe pai aponta para o real, Isso é chamadoTransformação para cima
A referência da classe pai só pode acessar suas próprias coisas e não pode acessar as propriedades ou métodos exclusivos da subclasse
Resumo de uma frase: a classe pai refere-se ao objeto da subclasse
O momento da transformação para cima:
Existem três tipos:
- Atribuição direta
Animal animal = new Bird();
- Parâmetro de método
public static void func(Animal animal) {
}
public static void main(String[] args) {
Dog dog = new Dog();
func(dog);
}
- Valor de retorno do método
public static Animal func() {
Dog dog = new Dog();
return dog;
}
Abatido
A transição para baixo não será segura, é melhor não usar ou usar menos
Animal animal = new Dog();
Dog dog = (Dog)animal; //需要强制类型转换
dog.wangwang(); //此时可以调用Dog特有的方法
Animal animal = new Dog();
//这里需要判断一下animal是不是Bird的一个实例,是的话才能向下转型
if(animal instanceof Bird) {
Bird bird = (Bird)animal;
bird.fly(); //此时可以访问Bird的特有方法
}
A instância de B A
é uma instância de B?
A se refere ao objeto de B antes?
Ligação de tempo de execução
class Animal {
public String name;
public int age;
public void eat() {
System.out.println("Animal::eat()");
}
}
class Dog extends Animal1{
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
}
}
Executar irá imprimir neste momentoAnimal :: comer ()
E vamos reescrever o método de comer para Cachorro
class Animal {
public String name;
public int age;
public void eat() {
System.out.println("Animal::eat()");
}
}
class Dog extends Animal1{
public void eat() {
System.out.println("Dog::eat()");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
}
}
Vai imprimirCachorro :: comer () Acima
Isso ocorre porque aconteceu durante o tempo de compilaçãoLigação de tempo de execução, Também chamadoLigação dinâmica。
Condições quando a ligação dinâmica ocorre
- Referências de classe pai referem-se a objetos de subclasse
- Chame o método de substituição com o mesmo nome da classe pai e da subclasse por meio da referência da classe pai
A ligação dinâmica ocorrerá neste momento, que também é a premissa do polimorfismo
Reescrever
Falando em reescrever aqui, tenho que revisar o recarregamento novamente.
Sobrecarga: [na mesma classe]
- Mesmo nome de método
- A lista de parâmetros é diferente
- O valor de retorno não é obrigatório
Substituir (substituir): [Na relação de herança]
Também chamado de substituir, substituir
- Mesmo nome de método
- A lista de parâmetros é a mesma
- O valor de retorno é o mesmo
Nota:
- Os direitos de acesso da classe infantil não podem ser inferiores aos direitos de acesso da classe pai
- O método a ser reescrito não deve ser um método estático
- O método a ser reescrito não deve ser finalizado
Entenda o polimorfismo
Deixe-me lhe dar um exemplo
class Shape {
public void draw() {
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("♦");
}
}
class Cricle extends Shape {
@Override
public void draw() {
System.out.println("⭕");
}
}
class Flower extends Shape {
@Override
public void draw() {
System.out.println("❀");
}
}
//===============================================================
public class TestDemo {
public static void drawMap(Shape shape) {
shape.draw();;
}
public static void main(String[] args) {
Rect rect = new Rect();
drawMap(rect);
Cricle cricle = new Cricle();
drawMap(cricle);
Flower flower = new Flower();
drawMap(flower);
}
}
Neste código, o código acima da linha divisória é Implementador de classe Escrito, o código abaixo da linha divisória é Chamador da classe Escrito.
Quando o chamador da classe está escrevendo o método drawMap, o tipo de parâmetro é Shape (a classe pai). No momento, ele não é conhecido dentro do método e não se importa com qual tipo (qual subclasse) a referência de forma atual aponta para. Instância. Neste ponto A referência de forma para chamar o método de desenho pode ter muitas manifestações diferentes(Relacionado à instância correspondente à forma), este comportamento é chamado Polimorfismo
Os benefícios do polimorfismo
- O custo de uso do chamador da classe é ainda mais reduzido
- O encapsulamento é feito para que o chamador da classe não precise saber os detalhes de implementação da classe
- O polimorfismo permite que o chamador de uma classe nem saiba qual é o tipo da classe, mas só precisa saber que o objeto possui um determinado método.
- Pode reduzir a "ciclocomplexidade" do código e evitar o uso de um grande número de if-else com
base no código agora. Se não for baseado em polimorfismo, o código será muito longo e complicado
public static void drawShapes() {
Rect rect = new Rect();
Cycle cycle = new Cycle();
Flower flower = new Flower();
String[] shapes = {
"cycle", "rect", "cycle", "rect", "flower"};
for (String shape : shapes) {
if (shape.equals("cycle")) {
cycle.draw();
} else if (shape.equals("rect")) {
rect.draw();
} else if (shape.equals("flower")) {
flower.draw();
}
}
}
Se você usar polimorfismo para conseguir, você não precisa escrever tantas instruções de desvio if-else, o código é mais simples
public static void drawShapes() {
// 我们创建了一个 Shape 对象的数组.
Shape[] shapes = {
new Cycle(), new Rect(), new Cycle(),
new Rect(), new Flower()};
for (Shape shape : shapes) {
shape.draw();
}
}
- Escalabilidade mais forte.
Se você deseja adicionar uma nova forma, o custo das alterações de código usando o polimorfismo também é relativamente baixo.
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("△");
}
}
essencial
O núcleo do polimorfismo éPara que o chamador não tenha que prestar atenção ao tipo específico do objeto