使用extends关键字可以实现继承的关系。不过extends本身意味着扩展已有类的功能,所以子类也可以称作派生类。
子类不能访问父类的私有成员,可以调用父类的非私有方法。(想要调用父类私有成员可以考虑getter和setter)
子类对象实例化之前先调用父类构造方法,再调用子类自己的构造方法。(先产生父类实例,再产生子类实例)
访问权限 private < default < public。如果需要子类覆写父类方法, 子类方法权限范围大于等于父类方法权限范围。
例如:父类-public 则子类public 父类-default 则子类default和public
父类-private 则子类随意
this和super代表方法时:
this调用本类属性,方法,super调用父类属性,方法。
this和super代表构造方法时:
一定要放在构造方法首行。
public class TestJava{
}
class Person{
private String name = "FangXy";
private int age = 14;
public Person(){
System.out.println("Father constructor is running!");
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
void tell01(){
System.out.println("Father -> output!(F-default S-default)");
}
void tell02(){
System.out.println("Father -> output!(F-default S-public)");
}
private void tell03(){
System.out.println("Father -> output!(F-private S-default)");
}
public void superTest(){
System.out.println("Super Test!(Running in the father class)");
}
public static void staticTest(){
System.out.println("Static Test!(Running in the father class)");
}
}
class Student extends Person{
private String school;
public Student(){
System.out.println("Son constructor is running!");
}
public void setSchool(String school){
this.school = school;
}
public String getSchool(){
return this.school;
}
void tell01(){
System.out.println("Son -> output!(F-default S-default)");
}
void tell02(){
System.out.println("Son -> output!(F-default S-public)");
}
void tell03(){
System.out.println("Son -> output!(F-private S-default)");
}
public void superTest(){
super.superTest();
System.out.println("SuperTest over!(Running in the son class)");
}
public void printInfo(){
System.out.println("SUPER/THIS TEST--");
System.out.println("Name:"+super.getName()+" Age:"+super.getAge()
+" School:"+this.school);
}
public static void staticTest(){
System.out.println("StaticTest over!(Running in the son class)");
}
}
class Demo{
public static void main(String[] args){
Student stu = new Student();
stu.setName("FangXy");
stu.setAge(17);
stu.setSchool("PekingUniversity");
System.out.println("Name:"+stu.getName()+" Age:"+
stu.getAge()+" School:"+stu.getSchool());
stu.tell01();
stu.tell02();
stu.tell03();
Person fat = new Person();
fat.setName("FuXs");
fat.setAge(12);
//fat.tell03();
//Main function can output in public and default case,
//cannot output in private case.
stu.superTest();
stu.printInfo();
Person.staticTest();
Student.staticTest();
}
}//Demo
输出:
Father constructor is running!
Son constructor is running!
Name:FangXy Age:17 School:PekingUniversity
Son -> output!(F-default S-default)
Son -> output!(F-default S-public)
Son -> output!(F-private S-default)
Father constructor is running!
Super Test!(Running in the father class)
SuperTest over!(Running in the son class)
SUPER/THIS TEST--
Name:FangXy Age:17 School:PekingUniversity
Static Test!(Running in the father class)
StaticTest over!(Running in the son class)
经过测试,static方法也是可以覆写的。
重载和覆写是不同的,虽然都是方法同名,
重载的方法在同一个类,条件是参数类型或个数或顺序不同。
覆写的方法在继承类中,条件是参数类型返回值类型什么的都相同,且子类方法权限松于或等于父类方法。
用final修饰的类不能被继承,用final修饰的变量成为常量,被final修饰的方法不能被重载。
否则会编译错误。
用final声明常量时,要求全部字母大写(规范,不大写也会编译通过)。
只要包含抽象方法就是抽象类。抽象类和抽象方法一定要加abstract修饰。
不过,
抽象类无法被实例化,否则会编译错误。
抽象方法只需要声明不需要实现。抽象类必须被子类继承。子类必须覆写抽象类中的全部抽象方法。否则会编译错误。
public class TestJava{
}
abstract class Person{
public abstract void print();
}
class Student extends Person{
public void print(){
System.out.println("Overriding the abstract function!");
}
}
class Demo{
public static void main(String[] args){
Student stu = new Student();
stu.print();
}
}//Demo
输出:
Overriding the abstract function!
抽象方法不能用final修饰,不然怎么被覆写...
同理抽象类不能用private修饰,不然怎么继承...
不过抽象类是可以有构造方法,毕竟也是一个类。
除了不能实例化,其他的比如抽象类中可以存在构造方法,子类用super调用抽象类的(有参和无参)构造方法。
接口和抽象类有相似,因为使用了抽象类。
接口中的属性是全局常量。(public+final)
接口中的方法是抽象方法。而且不管写没写public,接口中的方法一定是public的。
所以
interface A{
public static final String NAME = "FangXy";
public abstract void print();
public abstract String getName();
}
可以简写为
interface A{
String name = "FangXy";
void print();
String getName();
}
因为一个子类可以继承多个接口,所以可以用子类来完成多重继承,不过有一个问题就是要实现所有方法。
同样用内部类也可以完成多继承(参见上一篇内部类)。
覆写抽象类时,权限范围也应遵守覆写标准(子类松,父类紧,可相等)。
如果同时存在继承和接口。先继承后接口, extends C implements A,B
public class TestJava{
}
interface A{
void say01();
}
interface B{
void say02();
}
abstract class C{
public abstract void say03();
}
class Strudent extends C implements A,B{
public void say01(){
System.out.println("I am function say01!(from interface A)");
}
public void say02(){
System.out.println("I am function say02!(from interface B)");
}
public void say03(){
System.out.println("I am function say03!(from abstract class C)");
}
}
class Demo{
public static void main(String[] args){
Strudent stu = new Strudent();
stu.say01();
stu.say02();
stu.say03();
}
}//Demo
输出:
I am function say01!(from interface A)
I am function say02!(from interface B)
I am function say03!(from abstract class C)
不管前面继承了多少个抽象类,实现了多少个接口。背负了多少个抽象类,就一定都得实现。