【开开心心学java,快快乐乐写代码】面向对象的三大特性之一:继承

欢迎来到【开开心心学java,快快乐乐写代码】此专栏,本篇博客呢将会为大家仔细讲解关于面向对象的三大特性之一:继承。其他两大特性在我的主页里面也有,想了解的友友们欢迎垂阅。废话不多说,我们直接进入本篇博客正题----继承,光看这两个字是不是还是很抽象很模糊呢,不要担心,本博主依旧还是会讲的很仔细哒,认真看完,肯定会有所收获滴~

 

目录

​​​​​​​1、为什么需要继承

2、继承概念

3、继承的语法

4、父类成员的访问

5、supper关键字

6、子类的构造方法


​​​​​​​1、为什么需要继承

Java中使用类对现实世界中的实体来进行描述,类经过实例化之后会产生对象,对象则可以用来表示现实中的实体。但是现实世界有很多相似的实体,而某些实体也会有一些关联,在程序设计中也是这样。比如:我现在要设计猫和狗这两个类.

定义狗类:Dog.java

//Dog.java

public class Dog{
        string name;
        int age;
        float weight;
        public void eat(){
                System.out.println(name + "正在吃饭");
        }
        public void sleep(){
                System.out.println(name + "正在睡觉");
        }

        void mew(){
                System.out.println(name + "汪汪汪~~~");
        }
}

定义猫类:Cat.java 


public class Cat{
        string name;
        int age;
        float weight;
        public void eat(){
        System.out.println(name + "正在吃饭");
        }
        public void sleep(){
                System.out.println(name + "正在睡觉");
        }

        void mew(){
                System.out.println(name + "喵喵喵~~~");
        }

通过观察这两个类,我们不难发现,这两个类中有好多相同的代码,比如这些:

 我这里还只是写了两个动物类,如果我还要再写一个鸡类、鸭类或者更多其他动物的类呢,那可能会有更多重复的代码。于是java中就提出了继承的概念,将这些类的共性提出来,实验代码复用,减少重复的代码。


2、继承概念

 继承机制:是面向对象程序设计中实现代码复用的最重要手段,它允许程序员在原有类的特性的基础上扩展、增加新功能,从而形成一个新的类,这杨新形成的类就叫做派生类(子类)。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是实现代码复用。

例如:猫和狗都是动物,它们都有名字、年龄和体重,它们都需要吃饭和睡觉。因此我们可以把这些共性抽取出来,形成一个动物类。然后再具体写一个猫类或者狗类的时候直接继承动物类就行。在这里,动物类就相当于是父类(超类/基类),狗类或猫类就相当于是子类(派生类)。这时猫类或者狗类就有了之前抽取共性而组成动物类的特性,写猫类或狗类时就不需要再写那些共性特征了,并且可以在父类基础上进行扩展,比如增加属性或者方法。以继承的思想来达到共用可以实现代码复用。下面是画图的一个简单理解:

从继承的概念中可以看出,继承最大的作用就是可以实现代码复用和多态(下一篇博客中有多态的仔细讲解)。


3、继承的语法

在java中如果要表示类之间的继承关系,需要用到extends关键字。具体如下:

修饰符 class 子类名 extends 父类名{

        …………

}

下面是利用继承机制对上述所说猫狗类的一个重新设计:

public class Animal {
    String name;
    int age;
    float weight;
    public void eat(){
        System.out.println(name + "正在吃饭");
    }
    public void sleep(){
        System.out.println(name + "正在睡觉");
    }

}

public class Dog extends Animal {
    void mew(){
        System.out.println(name + "汪汪汪~~~");
    }
}

public class Cat extends Animal {
    void mew(){
        System.out.println(name + "喵喵喵~~~");
    }
}

public class Test{
    public static void main(String[] args) {
        Cat cat=new Cat();
        Dog dog=new Dog();
        // cat类中并没有定义任何成员变量,name属性肯定是从父类Animal中继承下来的
        System.out.println(cat.name);

        cat.mew();
        System.out.println(dog.name);
        dog.mew();
    }
}

运行结果:

在这段代码中可以很清楚的看到:Cat类和Dog类都继承了Animal类,所以在子类的类体中就没有再写那些已经从父类中继承过来的属性和方法注意:子类只能继承父类中没有用private修饰的字段或方法),在Test类中创建子类对象时,对象可以调用从父类继承过来的属性或方法。

注意:子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了。


4、父类成员的访问

在继承体系中,子类将父类中的方法和字段继承下来了,那在子类中能否直接访问父类中继承下来的成员呢?

子类中不存在与父类同名的变量时:

public class Base {
        int a;
        int b;
}
public class Derived extends Base{
        int c;
        public void method(){
                a = 10; // 访问从父类中继承下来的a
                b = 20; // 访问从父类中继承下来的b
                c = 30; // 访问子类自己的c

        }
}

子类中存在与父类同名的变量时:

public class Base {
        int a;
        int b;

        int c;


public class Derived extends Base{

        int a;//与继承过来的a重名

        char b;//与父类中成员b同名,但类型不同

        public void method(){

                a=100;//是访问父类继承的a,还是子类自己新增的a?

                b=101;// 访问父类继承的b,还是子类自己新增的b?

                c=102;// 子类没有c,访问的肯定是从父类继承下来的c

                // d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
        }
}
 


在子类方法中,或者通过子类对象去访问成员变量时:

  • 如果访问的成员变量子类中自己有,则优先访问自己的。
  • 如果访问的成员变量子类中无,而继承的父类中也没有,则编译报错。
  • 如果访问的成员变量与父类的成员变量名相同,则优先访问自己的成员,即:子类将父类成员隐藏了。

成员变量访问时遵循就近原则,先从子类中寻找,有就访问自己的,没有再向父类中寻找,如果父类中也没有,则编译报错。

访问成员方法时也是这样:

子类与父类的成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,先在子类方法中找,有则访问,无则在父类方法中寻找,有则访问,无则报错

子类与父类的成员方法名有相同时,通过子类对象访问子类与父类同名的方法时,优先访问子类自己的方法,而父类的同名方法将不会被访问到。如果对象访问的是父类和子类的方法名相同但参数列表不同的方法时,编译器会根据调用方法时传递的参数来匹配决定调用哪一个方法

问题:如果子类中存在与父类中相同的成员时,那如何在子类中访问父类相同名称的成员呢?


5、supper关键字

由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果需要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员

public class Base {
        int a;
        int b;

        public void methodA(){
                System.out.println("Base中的methodA()");
        }
        public void methodB(){

                System.out.println("Base中的methodB()");
        }
 }

public class Derived extends Base{
        int a; // 与父类中成员变量同名且类型相同
        char b; // 与父类中成员变量同名但类型不同

        public void methodB(){
                System.out.println("Derived中的methodB()方法");

        }

        public void methodC(){
                // 访问父类的成员变量时,需要借助super关键字
                // super是获取到子类对象中从父类继承下来的部分
                super.a = 200;
                super.b = 201;


                // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到
                methodB();

                // 如果在子类中要访问被重写的基类方法,则需要借助super关键字
                super.methodB(); // 访问基类的methodB()
                }

}

如果明确要访问到父类中与子类同名的成员,则必须使用supper关键字。

注意:supper关键字只能在非静态方法中使用。


6、子类的构造方法

java中规定,子类在调用自己的构造方法时,必须先调用父类的构造方法,然后再执行自己的构造方法

public class Base {

        public Base(){
                System.out.println("Base()");
        }
}
public class Derived extends Base{
        public Derived(){
                // super(); // 注意子类构造方法中默认会调用基类的无参构造方法:super(),
                // 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,并且只能出现一次

                System.out.println("Derived()");
        }
}
public class Test {
        public static void main(String[] args) {
                Derived d = new Derived();
        }
}

运行结果:

注意:

在类中,this(……)用于调用本类的构造方法supper用于调用父类的构造方法二者不能同时出现在构造方法中。

this是当前对象的引用,当前对象即调用该成员变量或方法的对象supper相当于是子类对象从父类继承过来的那一部分属性或方法的引用。可大致用以下图来表示:


 以上就是我要今天分享的内容啦,后续我还会继续更新的哒,常看我的博客会学到很多知识哦 

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
### 回答1: 好的,下面是一个冒泡排序的JavaScript代码实现: ``` // 定义一个函数用于实现冒泡排序 function bubbleSort(arr) { // 定义一个变量用于表示是否发生交换的标志 let swapped; // 循环遍历数组中的每一个元素 for (let i = 0; i < arr.length; i++) { // 初始化标志变量为 false swapped = false; // 内层循环,用于比较相邻的两个元素并交换位置 for (let j = 0; j < arr.length - i - 1; j++) { // 如果前一个元素比后一个元素大,则交换它们的位置 if (arr[j] > arr[j + 1]) { // 交换两个元素的位置 let temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; // 设置标志变量为 true,表示发生了交换 swapped = true; } } // 如果标志变量为 false,表示没有发生交换,说明数组已经有序,可以退出循环 if (!swapped) { break; } } // 返回排序后的数组 return arr; } // 测试冒泡排序函数 let arr = [5, 3, 6, 2, 10]; console.log(bubbleSort(arr)); // 输出 [2, 3, 5, 6, 10] ``` 在上面的代码中,我们定义了一个 `bubbleSort` 函数用于实现冒泡排序。这个函数接受一个数组作为参数,并返回一个排序后的数组。 在函 ### 回答2: 当然可以帮你一个JavaScript版本的冒泡排序。 冒泡排序是一种简单但效率相对较低的排序算法,它通过比较相邻元素并交换它们的位置,将较大的元素逐渐“冒泡”到数组的末尾。 以下是一个使用JavaScript实现的冒泡排序函数: ```javascript function bubbleSort(arr) { var len = arr.length; for (var i = 0; i < len - 1; i++) { for (var j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { // 交换相邻元素的位置 var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } ``` 这个函数接受一个数组作为参数,然后使用两个嵌套的`for`循环来遍历数组。内部的循环通过比较相邻元素的大小并进行交换来不断将较大的元素移动到末尾。外部的循环控制对所有元素的比较和交换操作进行多次迭代,直到数组排序完成。 你可以调用这个函数来对任意数组进行冒泡排序。例如: ```javascript var arr = [4, 2, 1, 3, 5]; var sortedArr = bubbleSort(arr); console.log(sortedArr); // 输出 [1, 2, 3, 4, 5] ``` 希望这可以帮助到你!如果你有任何问题,可以随时再问我。 ### 回答3: 冒泡排序是一种简单的排序算法,它通过多次比较和交换来将列表中的元素按照升序或降序排列。以下是一个用JavaScript编的冒泡排序算法: ```javascript function bubbleSort(arr) { var len = arr.length; for (var i = 0; i < len - 1; i++) { for (var j = 0; j < len - i - 1; j++) { // 比较相邻的两个元素 if (arr[j] > arr[j + 1]) { // 交换两个元素位置 var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } // 示例 var unsortedArray = [5, 8, 3, 1, 9]; console.log(bubbleSort(unsortedArray)); ``` 以上代码中,`bubbleSort`函数接收一个数组作为参数,并使用两个嵌套的循环来比较并交换相邻的元素。外层循环控制排序次数,内层循环用于比较和交换元素。当发现前一个元素大于后一个元素时,它们会被交换位置。最终返回经过冒泡排序后的数组。 在示例中,原始数组`[5, 8, 3, 1, 9]`通过冒泡排序后,将变为`[1, 3, 5, 8, 9]`。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哆啦A梦的110

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

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

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

打赏作者

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

抵扣说明:

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

余额充值