Java语言基础-面向对象编程三步走之把大象放进去

面向对象编程进阶

继承

我们先定义两个类:

package com.advan.inher;

public class Person {
    String name;
    int age;

    public Person(){

    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}


-----------


package com.advan.inher;

public class Student {
    String name;
    int age;
    String major;

    public Student(){

    }
    public Student(String name,int age,String major){
        this.name = name;
        this.age = age;
        this.major = major;
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }

    public void study(){
        System.out.println("学习");
    }
}


--------
    
package com.advan.inher;

public class ExtendsTest {
    public static void main(String[] args) {
        Person p = new Person("小明",18);
        p.eat();

        Student s = new Student("小王",14,"大数据");
        s.eat();
    }

}

我们定义了一个Person类和一个Student类,这两个类好像并没有什么关系,但是仔细看看他们的类和方法,发现Person类的属性和方法Student类也都有,那么是不是可以把他们相同的部分提取出来放在一个类中,然后让另一个类继承这个类,这样的话就可以降低代码的冗余。

现在我们改写一下:

package com.advan.inher;

public class Person {
    String name;
    int age;

    public Person(){

    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}


-----------


package com.advan.inher;

public class Student extends Person{
// extends 继承
    String major;

    public Student(){

    }
    public Student(String name,int age,String major){
        this.name = name;
        this.age = age;
        this.major = major;
    }

    public void study(){
        System.out.println("学习");
    }
}

----------
    

package com.advan.inher;

public class ExtendsTest {
    public static void main(String[] args) {
        Person p = new Person("小明",18);
        p.eat();

        Student s = new Student("小王",14,"大数据");
        s.eat();
    }

}

我们删掉了Student类中继承自Person的属性与方法,但是ExtendsTest依旧没有报错。

我们定义了一个Person类,继承Person的Student类就是Person类的子类,相对于Person类就升级成了Student类的父类。

然后我们还可以定义很多其他的类继承与Person,这样Person类已有的属性与方法就可以不用写了。

好处:

  • 减少了代码的冗余,提高了代码的复用性
  • 便于功能的扩展
  • 继承是多态的前提

语法:

class A extends B{
	
}
A:子类,派生类,subclass    B:父类,超类,基类,supercalss

特殊点:

  • 子类内的属性与方法与父类的同名时,以子类为准

    package com.advan.inher;
    
    public class Person {
        String name;
        int age;
    
        public Person(){
    
        }
        public Person(String name,int age){
            this.name = name;
            this.age = age;
        }
    
        public void eat(){
            System.out.println("吃饭");
        }
    
        public void sleep(){
            System.out.println("睡觉");
        }
    }
    
    
    -----------
    
    
    package com.advan.inher;
    
    public class Student extends Person{
    // extends 继承
        String major;
    
        public Student(){
    
        }
        public Student(String name,int age,String major){
            this.name = name;
            this.age = age;
            this.major = major;
        }
        
        public void eat(){
            System.out.println("去食堂吃饭");
        }
    
        public void study(){
            System.out.println("学习");
        }
    }
    
    ----------
        
    
    package com.advan.inher;
    
    public class ExtendsTest {
        public static void main(String[] args) {
            Person p = new Person();
            p.eat();
    
            Student s = new Student();
            s.eat();
        }
    
    }
    
    ---------
    吃饭
    去食堂吃饭
    

    第二次调用输出的是学生类中的eat方法,而不是继承自人类的eat方法。

  • 父类中使用private声明的私有属性或方法,子类依旧可以继承,但是受封装性的影响子类无法直接使用。

    package com.advan.inher;
    
    public class Person {
        String name;
        private int age;
    
        public Person(){
    
        }
        public Person(String name,int age){
            this.name = name;
            this.age = age;
        }
    
        public void eat(){
            System.out.println("吃饭");
        }
    
        public void sleep(){
            System.out.println("睡觉");
        }
    }
    
    
    -----------
    
    
    package com.advan.inher;
    
    public class Student extends Person{
        String major;
    
        public Student(){
    
        }
        public Student(String name,int age,String major){
            this.name = name;
            this.age = age;   // 父类的age修改为私有的,这里报错
            this.major = major;
        }
        
        public void eat(){
            System.out.println("去食堂吃饭");
        }
    
        public void study(){
            System.out.println("学习");
        }
    }
    
    ----------
        
    
    package com.advan.inher;
    
    public class ExtendsTest {
        public static void main(String[] args) {
            Person p = new Person();
            p.eat();
    
            Student s = new Student();
            s.eat();
        }
    
    }
    
    ---------
    吃饭
    去食堂吃饭
    

注意点:

  • Java只支持单继承或多层继承,不允许多重继承。

    意思是子类继承的父类也可以是另一个类的子类,但是子类不能同时有多个父类。

  • 父类可以派生多个子类。

  • 子父类是相对概念

  • 子类直接继承的父类叫做直接父类,间接继承的父类叫做间接父类

  • 子类继承直接父类与所有间接父类的属性与方法

  • 同名的属性与方法按照最近的一个为准

package com.advan.mlinher;

public class Person {
    String name;
    int age;

    public Person(){

    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}


-----------


package com.advan.mlinher;

public class Student extends Person{
    String major;

    public Student(){

    }
    public Student(String name,int age,String major){
        this.name = name;
        this.age = age; 
        this.major = major;
    }
    
    public void eat(){
        System.out.println("去食堂吃饭");
    }

    public void study(){
        System.out.println("学习");
    }
}

----------

package com.advan.mlinher;

public class Creature extends Student {
    public Creature(){

    }
    public Creature(String name,int age,String major){
        this.name = name;
        this.age = age;
        this.major = major;
    }
}
    
----------

package com.advan.mlinher;

public class ExtendsTest {
    public static void main(String[] args) {
        Creature s = new Creature();
        s.eat();
    }

}

---------
去食堂吃饭

补充:Object类

我们自己写的类,比如上面的Creature类,我们在调用他的属性和方法时,处理我们自己定义的,还出现了好多看起来眼熟但是不是我们定义的方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fXoaYPla-1590053349245)(https://i.loli.net/2020/05/20/sY9LXgCKnTAjOBF.jpg)]

原因是我们定义的所有类,都隐式继承object类,即object类是所有类的父类。这类似python中的type元类。

是语言内置的一个用来定义类的类。

练习:

题目:

(1) 定义一个ManKind类,包括:
成员变量int sex和int salary
方法void manOrWoman():根据sex的值显示"man"(sex == 1)或"woman"(sex == 0)
方法void employeed():根据salary的值显示"no job"(salary == 0)或"job"(salary != 0)

(2) 定义类Kids继承ManKind,并包括:
成员变量int yearsOld
方法printAge()打印yearsOld的值

(3) 定义类Kids Test,在类的main方法中实例化Kind的对象someKid,用该对象访问父类的属性与方法

package com.advan.lx;

public class ManKind {
    int sex;
    int salary;

    public ManKind(){

    }

    public ManKind(int sex,int salary){
        this.sex = sex;   
        this.salary = salary;
    }

    public void manOrWoman(){
        if(sex == 1){
            System.out.println("man");
        }else if(sex == 0){
            System.out.println("woman");
        }
    }

    public void employeed(){
        if(salary == 0){
            System.out.println("no job");
        }else if(salary != 0){
            System.out.println("job");
        }
    }
}

----------

package com.advan.lx;

public class Kids extends ManKind{
    int yearsOld;

    public Kids(){

    }

    public Kids(int sex,int salary,int yearsOld){
        this.sex = sex;
        this.salary = salary;
        this.yearsOld = yearsOld;
    }

    public void printAge(){
        System.out.println(yearsOld);
    }
}

----------

package com.advan.lx;

public class KidsTest {
    public static void main(String[] args) {
        Kids someKid = new Kids(1,0,10);
        someKid.printAge();
        someKid.manOrWoman();
        someKid.employeed();
    }
}

方法重写

定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置,覆盖。在程序执行过程中,子类的方法覆盖父类的方法。

在上面说明继承特殊点的例子其实就是重写的表现:

package com.advan.inher;

public class Person {
    String name;
    int age;

    public Person(){

    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}


-----------


package com.advan.inher;

public class Student extends Person{
// extends 继承
    String major;

    public Student(){

    }
    public Student(String name,int age,String major){
        this.name = name;
        this.age = age;
        this.major = major;
    }
    
    public void eat(){
        System.out.println("去食堂吃饭");
    }

    public void study(){
        System.out.println("学习");
    }
}

----------
    

package com.advan.inher;

public class ExtendsTest {
    public static void main(String[] args) {
        Person p = new Person();
        p.eat();

        Student s = new Student();
        s.eat();
    }

}

---------
吃饭
去食堂吃饭

重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名参数的方法时,实际执行的是子类重写父类的方法。

重写的规则:

  • 方法名与形参列表一致
  • 子类重写的方法的权限修饰符不小于父类的权限修饰符(private声明的方法除外)
  • 约定俗成:子类中叫重写的方法,父类中叫被重写的方法。
  • 被重写方法的返回类型是void,子类重写方法的返回类型也只能是void
  • 被重写方法的返回类型是A类型,子类重写方法的返回类型可以是A类或A的子类
  • 被重写方法的返回类型是基本数据类型,子类重写方法的返回类型必须是基本数据类型

访问权限修饰符

package com.advan.juri;

public class Order {
    private int orderPrivate;
    int orderDefault;
    protected int orderProtected;
    public int orderPublic;

    private void methodPrivate(){
        orderPrivate = 1;
        orderDefault = 2;
        orderProtected = 3;
        orderPublic = 4;
    }

    void methodDefault(){
        orderPrivate = 1;
        orderDefault = 2;
        orderProtected = 3;
        orderPublic = 4;
    }

    protected void methodProtected(){
        orderPrivate = 1;
        orderDefault = 2;
        orderProtected = 3;
        orderPublic = 4;
    }

    public void methodPublic(){
        orderPrivate = 1;
        orderDefault = 2;
        orderProtected = 3;
        orderPublic = 4;
    }
}

----------

package com.advan.juri;

public class OrderTest {
    public static void main(String[] args) {
        Order order = new Order();

        // order.orderPrivate = 1;  private 只能在类内部使用
        order.orderDefault = 1;
        order.orderProtected = 1;
        order.orderPublic = 1;

        // order.methodPrivate();
        order.methodDefault();
        order.methodProtected();
        order.methodPublic();
    }
}

----------

package com.advan.juri1;

import com.advan.juri.Order;

public class Order1 extends Order{
    public void method(){
        orderProtected = 1;	// order1是order的子类,虽然他们不在一个包下面,但是依旧可以使用protected权限修饰符标识的属性和方法
        orderPublic = 2;

        methodProtected();
        methodPublic();
    }
}

----------

package com.advan.juri1;

import com.advan.juri.Order;

public class Order2 {
    public void methon(){
        Order order = new Order();
        // 这里不是在一个包下,也没有子父类关系,但是在一个工程中,就可以使用public权限修饰符修饰的属性和方法。
        order.orderPublic = 1;
        order.methodPublic();
    }
}

super

super,可以理解为父类的,可以和this一起理解。

可以用来调用属性、方法、构造器

  • 调用属性

    package com.advan.supers;
    
    public class SuperTest {
        public static void main(String[] args) {
            Student s = new Student();
            s.con();
        }
    }
    
    ----------
    
    package com.advan.supers;
    
    public class Person {
        String name;
        int age = 30;
    }
    
    ----------
    
    package com.advan.supers;
    
    public class Student extends Person{
    
        int age = 18;
        String major;
    
        public void con(){
            System.out.println(this.age);
            System.out.println(super.age);
        }
    }
    
    ----------
    18
    30
    
  • 调用方法

    package com.advan.supers;
    
    public class SuperTest {
        public static void main(String[] args) {
            Student s = new Student();
            s.con();
        }
    }
    
    ----------
    
    package com.advan.supers;
    
    public class Person {
        String name;
        int age = 30;
    
        public void sleep(){
            System.out.println("睡觉");
        }
    }
    
    ----------
    
    package com.advan.supers;
    
    public class Student extends Person{
    
        int age = 18;
        String major;
    
        public void sleep(){
            System.out.println("回宿舍睡觉");
        }
    
        public void con(){
            this.sleep();
            super.sleep();
        }
    
    }
    
    ----------
    回宿舍睡觉
    睡觉
    
  • 调用构造器

    package com.advan.supers;
    
    public class Person {
        String name;
        int age;
    
        public Person(String name,int age){
            this.name = name;
            this.age = age;
        }
    }
    
    
    -----------
    
    
    package com.advan.supers;
    
    public class Student extends Person{
        String major;
        int age;
    
        public Student(String name,int age,String major){
            super(name,age);
            this.major = major;
        }
    
        public void show(){
            System.out.println(this.age);
            System.out.println(super.age);
        }
        
    }
    
    
    ----------
      
        
    package com.advan.supers;
    
    public class SuperTest {
        public static void main(String[] args) {
            Student s = new Student("小明",20,"大数据");
            s.show();
        }
    
    }
    
    ---------
    0
    20
    

子类对象实例化

子类继承父类后,就获得了父类中声明的属性或方法。

创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。

当我们通过子类构造器创建子类对象时,我们会直接或间接调用父类构造器,然后一直调用到object类构造器为止。然后子类对象才算正式初始化完成。

多态

多态就是一句话:一个对象指向两个类。

多态即多种状态,一个状态表示一个类。

我记得我在python类那一个博文里举的例子是:
小明是个学生,也是个北京人,他具有两种表示身份的状态,这就是多态。

java和python的多态不同的是:

python是子类对象是子类类型的同时也是父类类型。

java是使用子类构造器实例化父类对象。

前者可以有多重状态(python支持多继承),后者就只有两种状态(子类,父类)。

语法:

父类名 对象名 = new 子类构造器;

package com.advan.inher;

public class Person {
    String name;
    int age;

    public Person(){

    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}


-----------


package com.advan.inher;

public class Student extends Person{
    String major;

    public Student(){

    }
    public Student(String name,int age,String major){
        this.name = name;
        this.age = age;
        this.major = major;
    }
    
    public void eat(){
        System.out.println("去食堂吃饭");
    }

    public void study(){
        System.out.println("学习");
    }
}

----------
    

package com.advan.inher;

public class ExtendsTest {
    public static void main(String[] args) {
        Person p = new Student();
        p.eat();
        
        System.out.println(p instanceof Person);
        System.out.println(p instanceof Student);
    	// instanceof关键字   判断对象是什么类型,返回布尔值
    }

}

---------
去食堂吃饭
true
true

多态本质是一个转型的过程,多态是向上转型(使用子类构造器声明父类对象,有用小子造老子的赶脚)。

还有一个向下转型(使用父类构造器声明子类对象,这才是真二八经的老子造小子)

语法:

子类名 变量名 =(子类名) 父类对象;

package com.advan.inher;

public class ExtendsTest {
    public static void main(String[] args) {
        Person p = new Person();
        Student s = (Student) p;
        // int i = 1;
        // double d = (int) i;
    }

}

没错,就是强制类型转换。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寒 暄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值