Java种类学习,学习Java中相遇的后续难题

子类只能继承父类所有非私有的成员(成员方法和成员变量)

概述
多个类中存在相同的属性和行为时,可以把这些内容抽取到单独的一个类中。通过extends关键字可以实现继承.单独的这个类叫做父类,基类或者超类。多个类可以称为子类或者派生类。

1.代码块

子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法

作用

(1)在java中,使用 { } 括起来的代码 被称为代码块

class Father {    //私有属性    private int num = 10;    public int num2 = 20;        //私有方法    private void method() {        System.out.println;        System.out.println;    }        public void show() {        System.out.println;            System.out.println;    }}class Son extends Father {  public void function() {        //err        //num 在 Father 中是 private 访问控制        //子类不能继承父类私有成员变量        //System.out.println;            System.out.println;    }}public class ExtendsDemo {    public static void main(String[] args) {        Son s = new Son();        //子类不能继承父类的私有方法                //s.method();            s.show();        s.function();    }}    
  • 提高了代码复用性
  • 提高了代码的维护性
  • 让类和类之间产生了关系,是多态的前提(其实也是继承的弊端,类的耦合性增加了)
    开发的原则:低耦合,高内聚
    耦合:类与类的关系
    内聚:就是自己完成某件事情的能力

(2)分类:

调用子类构造方法时默认访问父类中无参构造方法(子类初始化之前,一定要先完成父类数据的初始化)

Java中继承的特点

A:局部代码块

【局部位置】

【作用:用于限定 变量的生命周期】

图片 1

B:构造代码块

【在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。】

【作用:可以把多个构造方法的共同 代码放到一起,对对象进行初始化】

图片 2

C:静态代码块

【在类的成员位置,用{}括起来的代码,只不过它用static修饰了】

【作用:一般是对类进行初始化】

图片 3

如果在父类中有公有的get/set方法,可以访问到父类中的私有属性:通过显式调用父类带参构造方法

  • Java中只支持单继承,不支持多继承
  • Java支持多层继承(继承体系)

(3)结论:

//抽象动物类abstract class Animal {    //姓名    private String name;    //年龄    private int age;        public Animal() {}        public Animal(String name,int age) {        this.name = name;        this.age = age;    }        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 abstract void eat();}//定义具体的狗类class Dog extends Animal {    public Dog() {}        public Dog(String name,int age) {        //试图这样对name和age初始化会报错        //name 在 Animal 中是 private 访问控制        //this.name = name;        //this.age = age;                //通过访问父类带参构造来初始化                super;    }        public void eat() {            System.out.println("Dog");    }}//测试类省略

继承的注意事项

A:执行顺序 :

【静态代码块 > 构造代码块 > 构造方法】

B:静态代码块:只执行一次

C:构造代码块:每次调用构造方法都会执行

  • 子类只能继承父类所有非私有的成员方法和成员变量
  • 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法
  • 不要为了部分功能而去继承
    什么时候考虑使用继承?继承其实是一种关系”is a”

2.继承

继承中成员变量的关系

(1)把多个类中相同的成员给提取出来
定义到一个独立的类中,然后让多个类和该独立类产生一个关系。

  • 子类中的成员变量和父类中的成员变量不一样
  • 子类中的成员变量和父类中的成员变量一样。就近原则

     这种关系,就叫做继承。

super 和 this 的区别
this 代表本类对象的引用。super
代表父类存储空间的标识,可以理解为父类的引用。

(2)Java中表示继承

  • 成员变量的调用

A:用关键字  extends 表示

B:格式

图片 4

(3)继承的好处:

  this.成员变量  调用本类的成员变量
  super.成员变量  调用父类的成员变量

A:提高了代码的复用性

B:提高了代码的维护性

C:让类与类产生了一个关系,是多态的前提

  • 构造方法的调用

(4)继承的弊端:

A:让 类的耦合性增强。这个类的改变,会影响其他和该类相关的类

【原则:低耦合,高内聚 】

【耦合:类与类的关系】

【内聚:自己完成某件事情的能力】

B:打破了封闭性

  this(...)    调用本类的构造方法
  super(...)   调用父类的构造方法

(5)Java中继承的特点:

  • 成员方法的调用

A:Java中类只支持单继承

B:Java中可以多层继承

(6)继承的注意事项

  this.成员方法    调用本类得成员方法
  super.成员方法   调用父类得成员方法

A:子类不能继承父类的私有成员

B:子类不能继承父类的构造方法,但可以通过 super 去访问

C:不要为了部分功能而去继承

ExtendsDemo

(7)什么时候使用继承

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();
    }
}

A:继承体现 的是:is  a  的关系(苹果 is a 水果)

B:采用假设法

ExtendsDemo2

(8)Java继承中的成员关系

/**
 * 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();
    }
}

A:成员变量

【子类的成员变量名称 和 父类的成员变量名称 不一样】

【子类的成员变量名称 和 父类的成员变量名称 一样】

图片 5

【子类中 调用父类中 指定成员变量 】

图片 6

B:构造方法

【子类的构造方法默认会去访问父类的无参构造方法】

图片 7

【子类中如果没有无参构造方法】

方法一:在父类中加一个带参数的构造方法

方法二:通过super关键字去显示的调用父类的带参数构造方法 

图片 8

方式三:子类通过this去调用本类的其他构造方法

【子类中一定要有一个去访问父类的构造方法,否则父类数据就没有初始化】

【注】this(…) 和 super(…)
必须放在第一条语句,否则会对父类进行多次初始化

图片 9

C:成员方法

【子类的成员方法名称 和 父类的成员方法名称 不一样】

【子类的成员方法名称 和 父类的成员方法名称 一样】

图片 10

ExtendsDemo3

(9)this与super

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();

    }
}

A:区别

【this代表本类对应的引用】

【super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)】

B:使用

【调用成员变量】

this.成员变量–调用本类的成员变量

super.成员变量–调用父类的成员变量

【调用构造方法】

this(…)–调用本类的构造方法

super(…)–调用父类的构造方法

【调用成员方法】

this.成员方法–调用本类的成员方法

super.成员方法–调用父类的成员方法

继承中构造方法的关系

  • 子类中所有的构造方法默认都会访问父类中无参的构造方法
  • 原因:因为子类会继承父类的数据,甚至还会使用父类的数据。所以,子类初始化前,一定要先完成父类的初始化
  • 子类中每一个构造方法的第一个语句默认是 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的带参构造方法

3.方法的重写(Override)

继承中成员方法关系

  • 子类中的方法和父类中的方法声明不一样

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

(1)定义:

方法重写

子类中出现了和父类中方法声明一摸一样的方法。
当子类中,需要使用父类的功能,而功能主题有自己持有内容时,可以重写父类中的方法。这样,既沿袭了父类的功能,又定义了子类持有的内容。可以通过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");
    }
}

注意

  • 父类中的私有方法,不能被重写。因为父类的私有方法,子类根本无法继承。
  • 子类重写方法时,访问权限不能更低。只能大于等于父类的权限,最好一致。

问题

  1. override 和overload 的区别,能改变返回值类型吗?
    方法重写(override):在子类中出现和父类中一模一样的方法声明时。
    方法重载(overload):同一个类中,出现方法名相同,参数列表不同。方法重载可以改变返回值的类型,因为它与返回值类型无关。方法重写不可以。

  2. 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();
    }
}

子类中出现了和父类中方法声明一模一样的方法

(2)应用:

当子类需要父类的功能,而功能主体子类有自己特有的内容时,可以重写父类中的方法。这样,既沿袭了父类的功能,又定义了子类特有的内容

(3)使用方式:

图片 11

(4)注意事项

A:父类中私有方法不能被重写

【因为父类 私有方法,子类根本就无法继承】

B:子类重写父类方法时,访问权限不能更低

【子类权限 最好 和父类一致】

图片 12

C:父类静态方法,子类也必须通过静态方法进行重写

【这个算不上重写,但是现象确实如此】

图片 13

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website