Java基础语法(六)
继承
一 面向对象继承
类继承
语法:
class 子类 extends 父类 {}
继承结构中,很多情况会把子类称为派生类,把父类称作超类(后面会有一个关键字super
)
eg:
定义一个狗类(Dog),成员属性有 name, age, sex,方法有eat(), snore() -->(打鼾)
一个猪类(Pig),成员属性有 name, age, sex, 方法有eat(), watch()
父类(Animal)
//定义父类Animal
public class Animal {
private String name;
private int age;
private String sex;
//定义无参构造方法
public Animal() {
}
//定义全参构造方法
public Animal(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
//定义set(),get()方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void eat() {
System.out.println("能吃是福!");
}
}
//定义子类Dog类
class Dog extends Animal {
public void watch() {
System.out.println("俺能看家");
}
}
//定义子类Pig类
class Pig extends Animal {
public void snore() {
System.out.println("吼呼吼呼吼俺会打鼾");
}
}
测试类:
public class Test {
public static void main(String[] args) {
Pig p = new Pig();
p.setName("佩奇");
p.setAge(21);
p.setSex("boy");
p.eat();
p.snore();
Dog d = new Dog();
d.setName("哮天犬");
d.setAge(44);
d.setSex("man");
d.eat();
d.watch();
}
}
如上例,Pig
和 Dog
有公共的成员属性 name, age, sex
,公共的方法 eat()
,把这些公共的属性,方法封装到一个父类 Animal
中,以达到精简代码,提高复用性.
子类对象实例化
eg:
子类对象实例化,观察无参构造调用
class Person {
public Person() { //父类无参构造
System.out.println("调用父类构造实例化对象");
}
}
class Student extends Person {
public Student() { //子类无参构造
System.out.println("调用子类构造实例化对象");
}
}
public class JavaDemo1 {
public static void main(String[] args) {
Student st = new Student(); //实例化子类对象
}
}
运行结果:
调用父类构造实例化对象
调用子类构造实例化对象
通过执行结果可见,父类构造会被默认调用,执行完毕才调用了子类构造.
实际上相当于子类的构造方法隐含了一个super()
.
但是如果父类没有提供无参构造时,就要通过super(参数...)
调用指定参数的构造方法,且必须放在子类构造方法首行.
继承限制
-
限制一
一个子类只能继承一个父类,存在单继承局限.class A {} class B {} class C extends A,B {} //[错误]一个子类只能继承一个父类
但是允许多层继承.(注意继承层次不能过多,不建议超过三层)
class A {} class B extends A {} class C extends B {}
-
限制二
对于所有的非私有(no private)操作属于显示继承;而所有的私有操作属于隐式继承.
eg
:
//定义父类
public class Person {
private int idNum; //私有成员属性 idNum
String name; //成员属性 name
public int getIdNum() { //获取私有属性
return idNum;
}
public void setIdNum(int idNum) {
this.idNum = idNum;
}
}
//定义子类
public class Student extends Person {
public Student(int idNum, String name) { //定义构造方法
setIdNum(idNum);
this.name = name;
}
public String getInfor() {
return "身份证号码: " + getIdNum();
}
}
//测试类
public class Test {
public static void main(String[] args) {
Student stu = new Student(456, "汤姆");
System.out.println(stu.getInfor());
System.out.println(stu.name);
}
}
运行结果:
身份证号码: 456
汤姆
二 覆写
方法覆写
在类继承结构中,子类可以继承父类所有方法,单父类方法无法满
足子类设计的需求时,就可以对已有的方法进行扩充,子类中,方法名,返回值类型,参数类型及个数与父类完全相同称为 方法覆写
.
eg
:
//父类定义
class Channel {
public void connect() { //父类定义方法
System.out.println("资源连接!");
}
}
//子类定义
class DatabaseChannel extends Channel {
public void connect() { //子类方法覆写,保留已有方法名称
System.out.println("数据库连接!");
}
}
public class Demo4 {
public static void main(String[] args) {
DatabaseChannel dataC= new DatabaseChannel(); //实例化子类对象
dataC.connect(); //调用被覆写的方法
}
}
运行结果:
数据库连接!
本例中,子类中定义了与父类结构完全相同的connect
方法,利用子类实例化对象调用connect
方法时调用的是被覆写的方法.
子类若想调用覆写前的方法,只能通过super.connect()
调用.
方法覆写限制
被子类覆写的方法不能拥有比父类更严格的访问控制权限;
如果父类的方法为private
,则子类无法覆写此方法.
三 final 关键字
Java里final
关键字用于定义不能被继承的类,不能被覆写的方法,常量和全局常量.
final class Demo1 {} //此类不能有子类
class Demo2 {
public final void connect() {} //方法无法被覆写
}
class Demo3 {
private final int ON = 1; //定义常量
}
class Demo4 {
public static final int ON = 1; //定义全局常量
}