作用:
提高了代码的复用性让类与类之间产生联系,为第三个特征多态提供了前提。注:
Java支持单继承(一个类只能有一个父类),不支持多继承(一个类可以有多个父类,C++支持)补充—继承体系:
学习一个继承体系时,先看顶层,体系中的共性方法都在那里。了解该体系中具备的基本功能 使用时,找体系最下面的对象何时定义继承:
当事物之间存在所属关系(is a)时,可以通过继承体现这个关系继承–私有的访问:
对于父类中私有的部分,子类是无法直接访问的。一般使用set,get方法 class Person{ //父类属性私有 private String name; //set方法 public void setName(String name){ this.name = name; } public String getName(){ return this.name; } } class Student extends Person{ } public class PrivateDemo{ public static void main(String args[]){ Student s = new Student(); s.setName("lily"); String a = s.getName(); System.out.print(a); } }示例
class species{ void show(){ System.out.println("吼叫"); } } class dog extends species{ void eat(){ System.out.println("骨头"); } } public class AbstractDemo{ public static void main(String args[]){ dog d = new dog(); d.eat(); d.show(); } }运行结果 注:
当父类private权限时,子类的权限大于或者等于父类都是无效的,因为此时private与权限无关,表明父类方法私有,无法调用和访问。话不多说,直接上代码~
class Father{ Father(){ System.out.println("I AM FATHER"); } } //子类继承父类 class Son extends Father{ Son(){ //有一个隐式的super();指向父类 System.out.println("I AM SON"); } } public class SuperDemo1{ public static void main(String args[]){ Son s = new Son(); } }效果图一出,惊了!子类会将父类中的构造方法一起运行,这是为啥?
原来是因为,在子类中,所有的构造函数的第一行都有一个默认的隐式super()语句 那么为什么子类对象初始化要先访问父类中的构造函数呢 这是因为子类继承了父类中的内容,所以创建对象时要先看父类是如何对内容进行初始化的 这就是子类的实例化过程
注意:
当父类中没有空参数构造函数时,子类需要通过显示定义super()语句指定要访问父类中的构造函数。用来调用父类构造函数的super语句在子类构造函数必须在第一行,因为父类的初始化要先完成 class Father{ //Father类中没有空构造函数 Father(int x){ System.out.println("father"); } } //子类继承父类 class Son extends Father{ Son(){ //使用super显示定义 super(3); System.out.println("Son"); } Son(int x){ super(x); System.out.println("Son1"); } } public class SuperDemo1{ public static void main(String args[]){ Son s = new Son(3); } }一些疑问~
this和super可以同时存在吗?
不可以,因为它们都只能定义在第一行为什么需要定义在第一行?
因为初始化动作要先完成当子父类中出现一样的方法时,子类对象运行的是子类的方法,这种特殊的情况,称为-----覆盖(override),又称重写,复写
概念:返回值类型,函数名,参数列表完全一致(很重要)
class father{ void show(){ System.out.println("show1"); } } //子类继承父类 class son extends father{ void show(){ System.out.println("show2"); } } public class ExtendDemo{ public static void main(String args[]){ son s = new son(); s.show(); } }解决方法-----super
使用super方法指向父类中的同名方法。
class father{ void show(){ System.out.println("show1"); } } //子类继承父类 class son extends father{ void show(){ System.out.println("show2"); //子类父类show方法重名,使用super指向父类中的show方法 super.show(); } } public class SuperDemo{ public static void main(String args[]){ son s = new son(); s.show(); } }注意1:
子类方法覆盖父类方法,必须要保证权限大于等于父类。静态只能覆盖静态,或者被静态覆盖。 //父类中show方法静态修饰而子类show方法无静态修饰 class Father{ static void show(){ System.out.println("father run!"); } } class Son extends Father{ void show(){ System.out.println("son run!"); } } public class StaticOverride{ public static void main(String args[]){ Son s = new Son(); s.show(); } }注意2:Java中不支持子类的多继承,而是通过接口来解决,将多继承变成多实现。
特点:
抽象方法都定义在抽象类中,都需要abstract修饰。抽象类不能实例化,即不能使用new关键字创建对象。子类要覆盖所有的抽象方法,子类具体化,子类可以创建对象。如果没有覆盖全部的抽象方法,子类还是一个抽象类。(在species类中加入一个抽象方法sleep,但子类dog没有覆盖sleep方法,则会报如下错误)
abstract class species{ //在种类中,若此时并不知晓物种的具体吼叫方式,那么将其抽象,使用abstract abstract void bellow(); abstract void sleep(); } 抽象类是不断的向上抽取而来的,抽取方法的声明但不确定具体的方法内容,由不同的子类来完成具体的方法内容。抽象类一定是一个父类。抽象类中可以不定义抽象方法,仅仅是为了让该类不创建对象,属于技巧应用。 abstract class species{ //在种类中,若此时并不知晓物种的具体吼叫方式,那么将其抽象,使用abstract abstract void bellow(); } class dog extends species{ void bellow(){ System.out.println("汪汪"); } void eat(){ System.out.println("骨头"); } } class cat extends species{ void eat(){ System.out.println("小鱼干"); } void bellow(){ System.out.println("喵喵"); } } public class AbstractDemo{ public static void main(String args[]){ dog d = new dog(); cat c = new cat(); d.eat(); d.bellow(); c.eat(); c.bellow(); } }运行结果 关于抽象类的几个问题 1.抽象类中有构造函数吗?
有,抽象类中的构造函数虽然不能给抽象类对象实例化,因为抽象类无法创建对象,但抽象类有子类,他的构造函数可以给子类的对象实例化2.抽象类和一般类的区别?
抽象类描述信息不具体,抽象类可以定义abstract方法,抽象类不可以实例化3.抽象关键字abstract不可以和哪些关键字共存?
final,private,static
注意:在调用接口的子类中,需要写权限修饰符,否则会报错 接口的特点:
接口不可以实例化。子类需要覆盖接口中的全部抽象方法,才可以实例化。接口是被implements的接口可以多实现。 interface InterA{ void show1(); } interface InterB{ void show2(); } //接口多继承 class son implements InterA,InterB{ public void show1(){ System.out.println("show1"); } public void show2(){ System.out.println("show2"); } } public class ExtendDemo{ public static void main(String args[]){ son s = new son(); s.show1(); s.show2(); } } 注:如果多实现的接口中方法名相同而内容不同,在调用时会出现不确定性。继承是为了获取基本功能,而接口是扩展功能。即使是使用接口中的某个方法,也需要全部覆盖,不然无法使用。 interface InterA{ void show1(); void show2(); void show3(); } class son implements InterA{ public void show1(){ System.out.println("show1"); } //需要全部覆盖 public void show2(){} public void show3(){} } public class ExtendDemo{ public static void main(String args[]){ son s = new son(); s.show1(); } }未完全覆盖报错信息
为了方便创建接口的子类对象,可以先创建一个类将接口中的方法全部实现,因该类的创建没有意义,所以将其抽象。之后的类需要接口中的内容时,就不需要完全覆盖,只需要继承该类。 abstract class demo implements InterA{ public void show1(){}; public void show2(){}; public void show3(){}; } interface InterA{ void show1(); void show2(); void show3(); } class son extends demo{ //implement InterA{ public void show2(){ System.out.println("show2"); } //public void show1(){} //public void show3(){} } public class ExtendDemo{ public static void main(String args[]){ son s = new son(); s.show2(); } }接口的思想
接口的出现扩展了功能。接口其实就是暴露出来的规则。接口的出现降低了耦合性,即解耦一方使用接口,一方实现接口接口和抽象类的区别
类与类之间是extends关系,是is和a。类和接口是implements关系,是like和a.抽象类中可以定义抽象和非抽象方法,子类可以直接使用,或覆盖使用。接口中定义都是抽象方法,必须实现才可使用。该文章为学习笔记,如有不足之处还请指正