子类与父类
由继承得到类是子类,被继承的类称为父类(超类)
子类
在类的声明中,使用关键字extends来定义一个类的子类,格式如下:
class 子类名 extends 父类名{
......
}
子类的继承性
子类和父类在同一包中的继承性
如果子类和父类在同一包中,那么子类自然继承父类中不是private的成员变量和成员方法作为自己的成员变量和成员方法,继承的成员变量和方法的访问权限保持不变
class People {
int age, leg = 2, hand = 2;
protected void showPeopleMess() {
System.out.printf("%d岁,%d只脚,%d只手\t", age, leg, hand);
}
}
class Student1 extends People {
int number;
public void tellNumber() {
System.out.printf("学号:%d\t", number);
}
public int add(int x, int y) {
return x + y;
}
}
class UniverStudent extends Student1 {
public int muti(int x, int y) {
return x * y;
}
}
public class Example5_1 {
public static void main(String[] args) {
Student1 zhang = new Student1();
zhang.age = 17;
zhang.number = 100101;
zhang.showPeopleMess();
zhang.tellNumber();
UniverStudent geng = new UniverStudent();
geng.age = 21;
geng.number = 6609;
geng.showPeopleMess(); // 这里假设 UniverStudent 可以访问 showPeopleMess 方法
geng.tellNumber();
int x = 10, y = 26; // 初始化变量 x
int result = geng.add(x, y);
System.out.printf("%d + %d = %d\n", x, y, result);
result = geng.muti(x, y);
System.out.printf("%d * %d = %d\n", x, y, result); // 使用乘法的格式字符串
}
}
成员变量的隐藏和方法重写
成员变量的隐藏
当子类所声明的成员变量与所继承的父类中成员变量名字相同,子类就会隐藏所继承的成员变量
方法重写
子类通过重写可以隐藏已继承的方法
语法规则
如果子类可以继承 父类的某个方法,那么子类就有权利重写这个方法 (不包括final),所谓方法重写就是子类中定义的方法的名字,参数个数,参数类型和父类的方法完全相同
重写的目的
子类通过方法的重写可以隐藏继承的方法,子类通过方法的重写可以把父类的状态和行为转化为自身的状态和行为
class A{
float computer(float x,float y){
return x+y;
}
public int g(int x,int y){
return x+y;
}
}
class B extends A {
float computer(float x,float y){ //对A中的方法进行重写
return x*y;
}
}
//class B extends A {
// double computer(float x,float y){
// return x*y;
// }
//} wrong
public class Example5_5 {
public static void main(String args[]){
B b=new B();
double result =b.computer(8,9);
System.out.println(result);
int m= b.g(12,8);
System.out.println(m);
}
}
重写的注意事项
在重写父类的方法时,不允许降低方法的访问权限,但可以提高访问权限(访问限制修饰符按访问权限从高到低的排列顺序是public->protected->友好的->private)
public class Example5_6 {
class A{
protected float f(float x,float y){
return x-y;
}
}
class B extends A{
// float f(float x,float y){ //非法,降低了访问权限
// return x*y;
}
class C extends A {
public float f(float x, float y) { //合法,提高了访问权限
return x * y;
}
}
}
super关键字
用super操作被隐藏的成员变量和方法
子类一旦隐藏了继承的成员变量和方法,那么子类创建的对象就不再拥有该变量和方法,该变量和方法将归关键字super负责(super.x,super.play() )
class Parent {
protected String hiddenVariable = "Parent's Variable";
public void hiddenMethod() {
System.out.println("Parent's Method");
}
}
class Child extends Parent {
private String hiddenVariable = "Child's Variable"; // 隐藏了父类的hiddenVariable
public void displayVariablesAndCallMethods() {
// 访问子类自己的变量
System.out.println("Child's variable: " + hiddenVariable);
// 使用super访问被隐藏的父类成员变量
System.out.println("Parent's variable via super: " + super.hiddenVariable);
// 调用子类自己的方法
this.hiddenMethod();
// 使用super调用被子类隐藏的父类方法
super.hiddenMethod();
}
}
public class Example5_7 {
public static void main(String[] args) {
Child child = new Child();
child.displayVariablesAndCallMethods();
}
}
使用super调用父类的构造方法
当用子类的构造方法构建一个子类的对象时,子类的构造方法总是先调用父类的某个构造方法的不带参数的构造方法,如果没有明确指出使用父类的哪个构造方法,子类就调用父类的不带参数的构造方法
由于子类不继承父类的构造方法,所以子类在其构造方法中需使用super来调用父类的构造方法,而且super必须是子类构造方法中的头一个语句,即如果在子类的构造方法中没有显示地写出super关键字来调用父类的某个构造方法,那么默认有:super();
class Parent1 {
protected String parentMessage = "Hello from Parent";
public Parent1() {
System.out.println("Parent constructor called.");
}
public Parent1(String message) {
parentMessage = message;
System.out.println("Parent constructor with message called: " + message);
}
}
class Child1 extends Parent1 {
private String childMessage;
// 使用super调用父类的构造方法
public Child1() {
super("Calling Parent constructor in Child"); // 显示地调用父类带有参数的构造函数
System.out.println("Child constructor called.");
childMessage = "Hello from Child";
}
public void displayMessages() {
System.out.println(parentMessage);
System.out.println(childMessage);
}
}
public class Example5_8 {
public static void main(String[] args) {
Child1 child = new Child1();
child1.displayMessages();
}
}
继承和多态
多态性就是指父类的某个方法被其子类重写时可以各自产生自己的功能行为
class Animal {
void cry() {
}
}
class Dog extends Animal {
@Override // 添加@Override注解,表示重写父类方法
void cry() {
System.out.println("汪汪汪");
}
}
class Cat extends Animal {
@Override // 添加@Override注解
void cry() {
System.out.println("喵喵喵");
}
}
public class Example5_11 {
public static void main(String[] args) {
Animal animal;
animal = new Dog();
animal.cry();
animal = new Cat();
animal.cry();
}
}
abstract类和abstract方法
用关键词abstract修饰的类称为abstract类(抽象类)
abstract class A{
...
}
对于abstract方法,只允许声明,不允许实现(没有方法体),而且不允许使用final和abstract修饰同一个方法或类,也不允许使用static和private修饰abstract方法
abstract类中可以有abstract方法
和普通类(非abstract)相比,abstract类中可以有abstract方法(非abstract类不可以有abstract类),也可以有非abstract方法
abstract class A{
abstract int min(int x,int y);
int max(int x,int y){
return x>y?x:y;
}
}
注:abstract类中也可以没有abstract方法
abstract类不能用new标识符创建对象
如果一个非抽象类是某个抽象类的子类,那么它必须重写父类中的抽象方法,给出方法体,这就是为什么不允许使用final和abstract同时修饰一个方法或类的原因
abstract类的子类
如果一个非抽象类是某个抽象类的子类,那么它必须重写父类中的抽象方法,给出方法体,如果一个抽象类是某个抽象类的子类,那么它可以重写父类中的抽象方法,也可以继承父类的抽象类
abstract类的对象做上转型对象
可以使用abstract类声明对象,尽管不能使用new标识符创建该对象,但该对象可以成为其子类对象的上转型对象,那么该对象就可以调用子类重写的方法
理解抽象类
1、抽象类抽象出的重要行为标准,是子类中必须中必须要有的行为标准
2、子类根据抽象类中的行为标准给出的具体行为
abstract class GirlFriend {
abstract void speak();
abstract void cooking();
}
class MyGirlFriend extends GirlFriend {
void speak() {
// 实现 speak() 方法
System.out.println("Hello!");
}
void cooking() {
// 实现 cooking() 方法
System.out.println("水煮鱼");
}
}
class Boy{
GirlFriend friend;
void setGirlFriend(GirlFriend f){
friend =f;
}
void showGirlFriend(){
friend.speak();
friend.cooking();
}
}
public class Example5_12 {
public static void main(String[] args) {
MyGirlFriend myGirlFriend = new MyGirlFriend();
Boy boy=new Boy();
boy.setGirlFriend(myGirlFriend);
boy.showGirlFriend();
}
}
若有侵权,请联系作者