概述:
多个类中存在相同的属性和行为时,可以把这些内容抽取到单独的一个类中。通过extends关键字可以实现继承.单独的这个类叫做父类,基类或者超类。多个类可以称为子类或者派生类。
作用:
- 提高了代码复用性
- 提高了代码的维护性
- 让类和类之间产生了关系,是多态的前提(其实也是继承的弊端,类的耦合性增加了)
开发的原则:低耦合,高内聚
耦合:类与类的关系
内聚:就是自己完成某件事情的能力
Java中继承的特点
- Java中只支持单继承,不支持多继承
- Java支持多层继承(继承体系)
继承的注意事项
- 子类只能继承父类所有非私有的成员方法和成员变量
- 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法
- 不要为了部分功能而去继承
什么时候考虑使用继承?继承其实是一种关系"is a"
继承中成员变量的关系
- 子类中的成员变量和父类中的成员变量不一样
- 子类中的成员变量和父类中的成员变量一样。就近原则
super 和 this 的区别
this 代表本类对象的引用。super 代表父类存储空间的标识,可以理解为父类的引用。
- 成员变量的调用
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
- 构造方法的调用
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
- 成员方法的调用
this.成员方法 调用本类得成员方法
super.成员方法 调用父类得成员方法
ExtendsDemo
package coco.perm;
/**
* Created by xingxingduan on 2016/5/2.
* 继承概述:
* 把多个类中相同的内容给提取出来定义到一个类中。
* 如何实现继承呢?
* Java提供了关键字:extends
* 格式:
*class 子类名 extends 父类名 {}
*
*/
class Person{
public void eat(){
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
class Student1 extends Person{}
//通过继承关系,省去大量的代码。子类可以继承父类未被private修饰的成员变量和成员方法。
class Teacher extends Person{}
public class ExtendsDemo {
public static void main(String[] args) {
Student1 s = new Student1();
s.eat();
s.sleep();
System.out.println("_________________________");
Teacher t = new Teacher();
t.eat();
t.sleep();
}
}
ExtendsDemo2
/**
* Created by xingxingduan on 2016/5/2.
* Java中继承的特点:
* 1、Java中只支持单继承,不支持多继承
* 有些语言支持多继承:格式:extends 类1,类2,...
* 2、Java支持多层继承(继承体系)
*/
class GrandFather{
public void show(){
System.out.println("我是爷爷");
}
}
class Father extends GrandFather{
public void method(){
System.out.println("我是老子");
}
}
class Son extends Father{}
public class ExtendsDemo2 {
public static void main(String[] args) {
Son s = new Son();
s.method();
s.show();
}
}
ExtendsDemo3
package coco.perm;
/**
* Created by xingxingduan on 2016/5/10.
* 继承的注意事项:
* A:子类只能继承父类所有非私有(未被private关键字修饰的)的成员(成员方法和成员变量)
* B:子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
* C:不要为了部分功能而去继承
*/
class Father{
private int num = 10;
public int num1 = 20;
//私有方法,子类不能继承
private void method(){
System.out.println(num);
System.out.println(num1);
}
public void show(){
System.out.println(num);
System.out.println(num1);
}
}
class Son extends Father{
public void function(){
//子类不能继承父类的私有成员变量
System.out.println(num1);
}
}
public class ExtendDemo3 {
public static void main(String[] args) {
Son s = new Son();
//之类不能继承父类的私有成员方法
s.show();
}
}
继承中构造方法的关系
- 子类中所有的构造方法默认都会访问父类中无参的构造方法
- 原因:因为子类会继承父类的数据,甚至还会使用父类的数据。所以,子类初始化前,一定要先完成父类的初始化
- 子类中每一个构造方法的第一个语句默认是 super()
class Father1 {
public Father1() {
System.out.println("这是Father的无参构造方法");
}
public Father1(String name) {
System.out.println("这是Father的带参数构造方法");
}
}
class Son1 extends Father1 {
public Son1() {
//子类的构造方法,默认第一天语句是super()
//super(); //可写可以不写
System.out.println("这是Son的无参构造方法");
}
public Son1(String name) {
//super();
System.out.println("这是Son的带参数构造方法");
}
}
public class ExtendsDemo {
public static void main(String[] args) {
Son1 s = new Son1();
System.out.println("-----------------");
Son1 s1 = new Son1("xingxing");
}
}
如果父类中没有无参构造方法,怎么办?
错误示例
class Father2{
public Father2(String name){
System.out.println("这是Father2的带参构造方法");
}
}
class Son2 extends Father2{
public Son2(){
System.out.println("这是Son2的无参构造方法");
}
public Son2(String name){
System.out.println("这是Son2的带参构造方法");
}
}
public class ExtendDemo2 {
public static void main(String[] args) {
Son2 s = new Son2();
}
}
程序报错:
Error:(11, 18) java: 无法将类 Father2中的构造器 Father2应用到给定类型;
需要: java.lang.String
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
解决方法:
- 在父类中加一个无参构造方法
- 通过使用super关键字去显示的调用父类中的带参构造方法
- 通过this去调用本类中的其他构造方法(子类中一定要有一个去访问了父类的构造方法,否则,父类的数据没有初始化)
class Father2{
public Father2(String name){
System.out.println("这是Father2的带参构造方法");
}
}
class Son2 extends Father2{
public Son2(){
super("随便填");
System.out.println("这是Son2的无参构造方法");
}
public Son2(String name){
//super("随便填");
this();
System.out.println("这是Son2的带参构造方法");
}
}
public class ExtendDemo2 {
public static void main(String[] args) {
Son2 s = new Son2();
System.out.println("-----分割线--------");
Son2 s2 = new Son2("coco");
}
}
运行结果:
这是Father2的带参构造方法
这是Son2的无参构造方法
-----分割线--------
这是Father2的带参构造方法
这是Son2的无参构造方法
这是Son2的带参构造方法
继承中成员方法关系
- 子类中的方法和父类中的方法声明不一样
class Father1{
public void show(){
System.out.println("show Father");
}
}
class Son1 extends Father1{
public void method(){
System.out.println("method Son");
}
}
public class ExtendsDemo1 {
public static void main(String[] args) {
Son1 s = new Son1();
s.show();
s.method();
}
}
运行结果:
show Father
method Son
- 子类中的方法和父类中的方法声明一样,先找子类本身,再找父类。
class Father1{
public void show(){
System.out.println("show Father");
}
}
class Son1 extends Father1{
public void show(){
System.out.println("show Son");
}
}
public class ExtendsDemo1 {
public static void main(String[] args) {
Son1 s = new Son1();
s.show();
}
}
输出结果:
show Son
方法重写
子类中出现了和父类中方法声明一摸一样的方法。
当子类中,需要使用父类的功能,而功能主题有自己持有内容时,可以重写父类中的方法。这样,既沿袭了父类的功能,又定义了子类持有的内容。可以通过super关键字调用。
class Phone{
public void call(String name){
System.out.println("给"+name+"打电话");
}
}
class NewPhone extends Phone{
public void call(String name){
super.call(name); //通过super关键字调用
System.out.println("可以听天气预报了");
}
}
public class ExtendsDemo3 {
public static void main(String[] args) {
NewPhone np = new NewPhone();
np.call("xingxing");
}
}
注意
- 父类中的私有方法,不能被重写。因为父类的私有方法,子类根本无法继承。
- 子类重写方法时,访问权限不能更低。只能大于等于父类的权限,最好一致。
问题:
override 和overload 的区别,能改变返回值类型吗?
方法重写(override):在子类中出现和父类中一模一样的方法声明时。
方法重载(overload):同一个类中,出现方法名相同,参数列表不同。方法重载可以改变返回值的类型,因为它与返回值类型无关。方法重写不可以。this 和 super的区别?
this代表当前类的引用
super代表父类存储空间的标识(可以理解为父类的引用,通过这个访问父类的成员)
练习案例
/**
* Created by v_xxingduan on 2015/6/22.
* 学生和老师的案例
*/
class Person{
//姓名
private String name;
//年龄
private int age;
public Person(){}
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
class Students extends Person{
public Students(){}
public Students(String name,int age){
super(name,age); //显示调用父类的带参构造
}
}
class Teacher extends Person{
public Teacher(){}
public Teacher(String name,int age){
super(name,age);
}
}
public class ExtendsDemo4 {
public static void main(String[] args) {
Students s1 = new Students();
s1.setName("xingxing");
s1.setAge(20);
System.out.println(s1.getName()+"----"+s1.getAge());
Teacher t1 = new Teacher("coco",21);
System.out.println(t1.getName()+"----"+t1.getAge());
}
}
/**
* Created by xingxingduan on 2015/6/22.
* 猫和狗的案例
*/
class Animal{
//姓名
private String name;
//年龄
private int age;
//颜色
private String color;
//构造方法
public Animal(){}
public Animal(String name,int age,String color){
this.name = name;
this.age = age;
this.color = color;
}
//成员方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setColor(String color) {
this.color = color;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getColor() {
return color;
}
}
class Cat extends Animal{
public Cat(){}
public Cat(String name,int age,String color){
super(name,age,color);
}
public void playGame(){
System.out.println("Cat PlayGame");
}
}
class Dog extends Animal{
String hobby;
public Dog(){}
public Dog(String name,int age,String color,String hobby){
super(name,age,color);
this.hobby = hobby;
}
public void lookDog(){
System.out.println("LookDog");
}
}
public class ExtendsDemo5 {
public static void main(String[] args) {
Cat c = new Cat();
c.setName("cat");
c.setAge(2);
c.setColor("balck");
System.out.println("name:"+c.getName()+"\tage:"+c.getAge()+"\tcolor:"+c.getColor());
c.playGame();
Dog d = new Dog("coco",3,"yellow","eat");
System.out.println("name:"+d.getName()+"\tage:"+d.getAge()+"\tcolor"+d.getColor()+"\thobby:"+d.hobby);
d.lookDog();
}
}