herdar
conceito de herança
Mecanismo de herança: É o meio mais importante da programação orientada a objetos para tornar o código reutilizável. Permite aos programadores estender e adicionar novas funções, mantendo as características da classe original. Isso gera uma nova classe, que é chamada de derivação. A herança apresenta a estrutura hierárquica da programação orientada a objetos e reflete o processo cognitivo do simples ao complexo. O principal problema que a herança resolve é: extração de características comuns e realização de reutilização de código.
Por exemplo: cães e gatos são ambos animais, então podemos extrair o conteúdo comum e então usar a ideia de herança para conseguir o compartilhamento.
Na ilustração acima, Cachorro e Gato herdam a classe Animal. A classe Animal é chamada de classe pai/classe base ou superclasse. Cachorro e Gato podem ser chamados de subclasse/classe derivada de Animal. Após a herança, a subclasse pode ser duplicado. Usando os membros da classe pai, a subclasse só precisa se preocupar com seus próprios membros recém-adicionados ao implementá-la.
Sintaxe herdada
Em Java, se você deseja expressar o relacionamento de herança entre classes, você precisa usar a palavra-chave extends, como segue:
修饰符 class 子类 extends 父类 {
// ...
}
Então redesenhe a cena na imagem acima usando herança:
primeiro crie o arquivo Animal.java
public class Animal{
String name;
int age;
float weight;
public void eat(){
System.out.println(name + "正在吃饭");
}
public void sleep(){
System.out.println(name + "正在睡觉");
}
}
Em seguida, crie o arquivo Dog.java
public class Dog extends Animal{
void bark(){
System.out.println(name + "在汪汪叫~~~");
}
}
Continue criando o arquivo Cat.Java
public class Cat extends Animal{
void mew(){
System.out.println(name + "在喵喵叫~~~");
}
}
Por fim, crie o arquivo TestExtend.java para teste
public class TestExtend {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(dog.name);
System.out.println(dog.age);
dog.eat();
dog.sleep();
dog. Bark();
}
}
Não há variáveis de membro definidas na classe Dog. Os atributos name e age devem ser herdados da classe pai Animal. Os métodos eat() e sleep() acessados por Dog também são herdados de Animal.
Perceber:
1. A subclasse herdará as variáveis ou métodos de membro da classe pai para a subclasse.
2. Depois que a subclasse herda a classe pai, ela deve adicionar seus próprios membros exclusivos para refletir a diferença da classe base, caso contrário, não há necessidade de herdar.
Acesso aos membros da classe pai
A subclasse e a classe pai não possuem variáveis de membro com o mesmo nome
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; // 访问从父类中继承下来的a
b = 20; // 访问从父类中继承下来的b
c = 30; // 访问子类自己的c
}
}
Subclasses e classes pai possuem variáveis de membro com o mesmo nome
public class Base {
int a;
int b;
int c;
}
public class Derived extends Base{
int a; // 与父类中成员a同名,且类型相同
char b; // 与父类中成员b同名,但类型不同
public void method(){
a = 100;
b = 101;
c = 102;
d = 103;// 编译失败,因为父类和子类都没有定义成员变量b
}
}
// 访问父类继承的a,还是子类自己的a?答案是自己的
// 访问父类继承的b,还是子类自己的b? 答案是自己的
// 子类没有c,访问的肯定是从父类继承下来的c
Ao acessar membros em um método de subclasse ou por meio de um objeto de subclasse:
Se a variável de membro a ser acessada existir em uma subclasse, acesse primeiro sua própria variável de membro. Se a variável membro acessada não existir na subclasse, ela será acessada herdada da classe pai. Se a classe pai não estiver definida, um erro de compilação será relatado. Se a variável-membro que está sendo acessada tiver o mesmo nome de uma variável-membro na classe pai, a sua própria será acessada primeiro. O acesso à variável membro segue o princípio da proximidade. Se você tiver uma, você tem prioridade. Caso contrário, você a encontrará na classe pai.
Os nomes dos métodos de membro são diferentes
// Base.java
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
}
// Derived.java
public class Derived extends Base{
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodB(); // 访问子类自己的methodB()
methodA(); // 访问父类继承的methodA()
method(); // 编译失败,在整个继承体系中没有发现方法methodD()
}
}
Resumo: Quando um método membro não tem o mesmo nome, ao acessar o método em um método de subclasse ou através de um objeto de subclasse, você acessará primeiro seu próprio método. Se você não o encontrar, você o procurará no classe pai. Se não existir na classe pai, um erro será relatado.
Métodos membros têm o mesmo nome
// Base.java
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
// Derived.java
public class Derived extends Base{
public void methodA(int a) {
System.out.println("Derived中的method(int)方法");
}
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),父类的无法访问到
}
}
Perceber:
Ao acessar métodos com nomes diferentes na classe pai e na subclasse por meio do objeto de subclasse, o método é primeiro pesquisado na subclasse e acessado se for encontrado. Caso contrário, o método é pesquisado na classe pai e acessado se for encontrado. Caso contrário, uma compilação erro é relatado. Ao acessar o método com o mesmo nome da classe pai e da subclasse através do objeto de subclasse, se a lista de parâmetros do método com o mesmo nome da classe pai e da subclasse for diferente (sobrecarregada), selecione o método apropriado para acessar de acordo com os parâmetros passados pelo método de chamada, caso contrário, será relatado um erro.
super palavra-chave
A principal função desta palavra-chave é acessar membros da classe pai em métodos de subclasse.
// Base.java
public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
// Derived.java
public class Derived extends Base{
int a;
char b;
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
// 对于同名的成员变量,直接访问时,访问的都是子类的
a = 100; // 等价于: this.a = 100;
b = 101; // 等价于: this.b = 101;
super.a = 200;
super.b = 201;
// 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
// 如果在子类中要访问重写的父类方法,则需要借助super关键字
methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),父类的无法访问到
super.methodB(); // 访问父类的methodB()
}
}
Perceber:
1. Super só pode ser usado em métodos não estáticos.
2. No método de subclasse, acesse as variáveis de membro e métodos da classe pai.
Construtor de subclasse
Pai e filho, pai e filho, primeiro há o pai e depois o filho, ou seja: ao construir um objeto de subclasse, você precisa primeiro chamar o construtor da classe pai e depois executar o construtor da subclasse.
// Base.java
public class Base {
public Base(){
System.out.println("Base()");
}
}
// Derived.java
public class Derived extends Base{
public Derived(){
// super(); // 注意子类构造方法中默认会调用父类的无参构造方 法:super(),
// 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,并且只能出现一次
System.out.println("Derived()");
}
}
// Test.java
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
}
/*
* 运行的结果为:
* Base()
* Derived()
*/
No método de construção de subclasse, nenhum código sobre a construção da classe pai é escrito, mas ao construir o objeto de subclasse, o método de construção da classe pai é executado primeiro e, em seguida, o método de construção da subclasse é executado, porque: o os membros do objeto de subclasse são. Consiste em duas partes, a parte herdada da classe pai e a parte recém-adicionada da subclasse. Ao construir um objeto de subclasse, você deve primeiro chamar o construtor da classe pai para concluir a construção dos membros herdados da classe pai e, em seguida, chamar o próprio construtor da subclasse para inicializar os membros recém-adicionados da subclasse .
Perceber:
1. Se a classe pai definir explicitamente um construtor sem parâmetros ou padrão, há uma chamada super() implícita por padrão na primeira linha do construtor da subclasse, ou seja, o construtor da classe pai é chamado.
2. Se o construtor da classe pai tiver parâmetros, o usuário precisará definir explicitamente o construtor da subclasse e selecionar o construtor da classe pai apropriado para chamar o construtor da subclasse, caso contrário a compilação falhará.
3. No método de construção de subclasse, quando super(...) chama a construção da classe pai, ela deve ser a primeira instrução na construção da subclasse.
4.super(...) só pode aparecer uma vez no construtor da subclasse e não pode aparecer ao mesmo tempo.
super e isso
Tanto super quanto this podem ser usados para acessar métodos de membro: variáveis de membro e chamadas de outras funções de membro podem ser usadas como a primeira instrução do construtor. Então, qual é a diferença entre elas?
Mesmo ponto:
- Todas são palavras-chave em Java.
- Ele só pode ser usado em métodos não estáticos de uma classe para acessar métodos e campos de membros não estáticos.
- Quando chamado em um construtor, deve ser a primeira instrução do construtor e não pode existir ao mesmo tempo.
diferença:
- Esta é uma referência ao objeto atual, que é o objeto que chama o método de instância.Super é equivalente a uma referência a alguns membros do objeto da subclasse herdado da classe pai.
- Em métodos de membros não estáticos, this é usado para acessar métodos e propriedades desta classe, e super é usado para acessar métodos e propriedades herdados da classe pai.
- No método construtor: this(...) é usado para chamar o método construtor desta classe, e super(...) é usado para chamar o método construtor da classe pai. As duas chamadas não podem aparecer no método construtor ao mesmo tempo.
- Deve haver uma chamada para super(...) no construtor, e o compilador irá aumentá-la se o usuário não escrever, mas this(...) não aumentará se o usuário não escrever.
Método de herança
Somente os seguintes métodos de herança são suportados em Java: