面向对象--------三巨头

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ ა
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
系列专栏:xiaoxie的Java系列专栏——CSDN博客●'ᴗ'σσணღ*
我的目标:"团团等我💪( ◡̀_◡́ ҂)" 

感谢您的阅读

( ⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​+关注(互三必回)!

Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),面向对象是一种编程范式,它将程序的组织方式从过程化的思维方式转变为以对象为中心的思维方式。在面向对象编程中,程序被组织成一组相互协作的对象,每个对象都有自己的状态和行为,并且可以通过消息传递来进行交互。面向对象的编程语言提供了类和对象的概念,通过定义类来创建对象,并通过对象之间的交互来实现程序的功能,Java面向对象有三大巨头------封装继承多态 。下文博主将一一介绍它们的语法以及优点等等。

一.封装

1.什么是封装

封装是面向对象编程中的一个重要概念,指的是将抽象出来的数据和对数据的操作封装在一起,形成一个类(或对象),使其只能通过类(或对象)提供的接口来访问和操作数据,同时隐藏了数据的实现细节,从而达到保护数据的安全和完整性的目的。通过封装,程序员可以将复杂的系统简化并提高代码的可维护性和可扩展性。

2.为什么要封装

封装的目的是保护数据的安全和完整性,同时隐藏数据的实现细节,提高代码的可维护性和可扩展性,具体有以下几个方面的好处:

  1. 保护数据的安全和完整性:封装可以将数据隐藏起来,使得外部代码无法直接访问和修改数据,从而防止数据被意外修改或篡改,提高数据的安全性和可靠性。

  2. 隐藏实现细节:封装可以隐藏数据的实现细节,将复杂的实现逻辑封装到类的内部,对外部代码来说,只需要关心调用类的接口即可,不必关心类的内部实现,降低了代码的耦合度,提高了代码的可维护性和可读性。

  3. 提高代码的可维护性和可扩展性:封装可以将数据和操作进行分离,使得修改数据的实现细节并不会影响对外部接口的调用方式,从而提高了代码的可维护性和可扩展性,方便系统的后续维护和升级。

3.该如何实现封装

Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:

访问限定符
NO范围privatedefault(默认)protectedpublic
1同一个包中的同一类☑️☑️☑️☑️
2同一个包中的不同类☑️☑️☑️
3不同包中的子类☑️☑️
4不同包中的非子类☑️

说明:访问限定符不仅可以限制成员属性的访问权限也可以限制类的访问权限;一般成员变量由private 所修饰 成员方法由 public所修饰;default :表示的是没有写访问限定符就默认为default所修饰

4.实例举例

public class Employee {
    private String name;   // 将属性进行封装
    private String department;   // 将属性进行封装
    private int age;   // 将属性进行封装
 
    public String getName() {
        return name;   // 只暴露出了获取属性的接口
    }
 
    public void setDepartment(String department) {
        this.department = department;   // 只暴露出了设置属性的接口
    }
 
    public void increaseAge() {
        age++;   // 只暴露出了对属性进行修改的接口
    }
}
 

在这个例子中,将员工的姓名、部门和年龄进行了封装,只在外部暴露了获取姓名和设置部门、增加年龄的接口,从而保护了属性的安全和完整性,同时隐藏了实现细节。

5.说明

当然以上举得例子只是封装一个小小的优点之一,等和继承与多态结合起来一起使用,你就会发现封装的妙用了

二.继承

1.什么是继承

继承是面向对象编程中的一个概念,它指的是一个类可以派生出新的类,新的类可以继承原来类的属性和方法,同时可以在原有基础上增加自己的属性和方法,从而达到代码复用的目的。继承可以通过子类来扩展或者修改父类的功能,提高代码的可维护性和可复用性。在继承关系中,被继承的类被称为父类或基类,继承的类被称为子类或派生类。

2.为什么要继承呢

首先让我们看一下下面的例子  

class Animal {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"正在吃");
    }
}
class Dog {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"正在吃");
    }
    public void Bark() {
        System.out.println(this.name+"汪汪叫");
    }
}
class Bird {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"正在吃");
    }
    public void Bugu() {
        System.out.println(this.name+"布谷布谷叫");
    }
}

从以上代码可以看出我们设计出的了三个类,相信细心的读者们可以发现这三个类有很多共性的地方,代码有很多的重复使用了,而继承就是为了解决这个问题

3.继承的使用

上述图示中,Dog和Bird都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Bird可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。
从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态

4.继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字,具体如下

class Animal {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"正在吃");
    }
}
class Dog extends Animal {
    
    public void Bark() {
        System.out.println(this.name+"汪汪叫");
    }
}
class Bird extends Animal {
   
    public void Bugu() {
        System.out.println(this.name+"布谷布谷叫");
    }
}

5.继承中的一些注意事项

1.Java只能单继承,不可以实现多继承

2.成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。

3.子类要想访问父类中的成员属性可以使用关键字 super()来访问如下图

class Animal {
    public String name = "小黑";
    public int age;
    public void eat() {
        System.out.println(this.name+"正在吃");
    }
}
class Dog extends Animal {
    public String name = "旺财";
    public void Bark() {
        System.out.println(this.name+"汪汪叫");
    }
    public void func() {
        System.out.println(super.name);
    }

}
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.func();
    }
}

结果如下

4.父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。

class Animal {
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println(this.name+"正在吃");
    }
}
class Dog extends Animal {

    public Dog(String name, int age, String sex) {
        super(name, age);
        this.sex = sex;
    }
    public String sex;
    public void Bark() {
        System.out.println(this.name+"汪汪叫");
    }
    public void func() {
        System.out.println(super.name);
    }

}

因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

注意:
1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现

5. super和this

super和this是两个关键字,都是用来引用对象或类的,但是它们有不同的作用和用法。

this关键字用于在一个类的方法中引用该类的成员变量、方法或构造函数。通常用于区分成员变量和方法名相同的情况。例如:

public class Person{
    private String name;
    
    public Person(String name){
        this.name = name;
    }
    
    public String getName(){
        return this.name;
    }
}

在上述代码中,this.name引用了该类的成员变量name,而非方法中的参数name。

super关键字用于在子类中引用父类的成员变量、方法或构造函数。通常用于在子类中重写父类的方法时,调用父类的方法或调用父类的构造函数。例如:

public class Animal{
    protected String name;
    
    public Animal(String name){
        this.name = name;
    }
    
    public void eat(){
        System.out.println("Animal is eating.");
    }
}

public class Cat extends Animal{
    public Cat(String name){
        super(name);
    }
    
    @Override
    public void eat(){
        super.eat(); //调用父类的eat方法
        System.out.println("Cat is eating.");
    }
}

在上述代码中,super(name)调用了父类Animal的构造函数,而super.eat()调用了父类Animal的eat方法。

6.封装在继承中的使用

1.private 即只能在自己类中被访问,父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了

2.default 即默认在同一个包内父类的default成员变量子类可以访问

3.protected 即在同一个包或者不同包的父类成员变量被protected修饰的子类可以访问

4.public 即都可以被访问

7.final的使用

在继承中,final关键字通常用于类、方法或属性上,用来表示其不能被子类继承或重写。

  1. 对于类,如果使用了final关键字修饰,则该类不能被其他类继承。

  2. 对于方法,如果使用了final关键字修饰,则该方法不能被子类重写。

  3. 对于属性,如果使用了final关键字修饰,则该属性不能在子类中被重新赋值。

使用final关键字有以下几个好处:

  1. 可以提高程序的安全性,避免子类对父类的重要方法或属性进行更改。

  2. 可以提高程序的性能,因为编译器可以对final修饰的方法或属性进行优化,减少运行时的开销。

  3. 可以使程序的设计更加灵活,因为final关键字可以限制子类的行为,从而保证代码的正确性和稳定性。 

8. 继承和组合

继承和组合是面向对象编程中常用的两种关系。它们的区别如下:

  1. 继承是一种“is-a”(是一个)的关系,即子类是父类的一种具体化,子类可以继承父类的属性和方法。而组合是一种“has-a”(拥有一个)的关系,即一个类拥有另一个类的对象作为自己的属性或成员。

  2. 继承是静态的关系,即子类在编译期已经确定了继承关系,而组合是动态的关系,即一个类可以在运行时动态地组合其他类的对象。

  3. 继承可以方便地实现代码的重用,减少了代码的冗余。但是过多的继承会导致类之间的耦合性增加,影响代码的灵活性。组合能够更灵活地组合各种对象,但是需要更多的代码来处理对象之间的关系。

  4. 继承可以直接访问父类的属性和方法,但是如果父类的实现发生改变,子类也需要相应地做出调整。组合需要通过调用对象的方法来访问其属性和方法,但是更容易适应变化。

三.多态

1.多态发生的前置条件

Java发生多态的条件包括:

  1. 继承:多态是通过父类和子类之间的继承关系实现的。

  2. 重写:子类必须重写父类的方法,才能实现多态。

  3. 向上转型:使用父类的引用指向子类的对象,从而实现多态。

  4. 运行时绑定:多态的方法调用在运行时进行绑定,而不是在编译时确定。这意味着程序在运行时才能确定调用的是哪个类的方法。

2.什么是向上转型呢

从上文中我们可以知道发生多态的条件之一就是发生向上转型,那什么是向上转移呢?

向上转型是指将一个子类对象转换为其父类对象的过程,即子类对象赋值给父类类型的变量。这种转型是安全的,因为子类对象具有父类对象所有的属性和方法,因此可以在父类类型的变量中使用。通常向上转型是多态性的基础之一。

举个例子,如果有一个动物类 Animal,和一个子类狗类 Dog,可以这样转型:

Animal animal = new Dog(); // 向上转型,将子类对象赋值给父类对象
//分解写就是
Dog dog = new Dog();
Animal animal = dog;

在这个例子中,Dog 对象 animal 实际上是一个 Animal 类型的变量,但是它仍然可以调用 Dog 类中定义的方法,因为 Dog 类继续了 Animal 类,所以 Dog 类对象拥有 Animal 类的所有属性和方法。

3.什么是重写

重写(override)是指在子类中实现一个与父类中同名、同参数列表的方法,并且这个方法的访问修饰符不能低于父类中的方法,目的是覆盖父类中的方法实现。在运行时,调用该方法时将优先执行子类中的实现。重写方法可以改变父类中的行为,实现多态性和动态绑定。

​class Animal {
    public String name;
    public int age;
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /* 4.private*/ /* 1.final*/ /*2.static*/ public void eat() {
        System.out.println(this.name+"正在吃....");
    }
}
class Dog extends Animal {
    public Dog(String name,int age ) {
        super(name,age);
    }

    @Override//重写,建议加上@Override编译器就会检测是否符合重写的语法
    public void eat() {
        System.out.println(this.name+"正在吃狗粮....");
    }
}
class Bird extends Animal {
    public Bird(String name, int age) {
        super(name, age);
    }

    @Override//重写
    public void eat() {
        System.out.println(this.name + "正在吃鸟粮....");
    }
}
public class text {
    public static void func(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
        func(new Dog("旺财",2));
        func(new Bird("布谷",1));

    }
}

4.多态,继承,封装的实现

// Animal 类定义
public class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public void makeSound() {
        System.out.println("动物发出叫声");
    }
}

// Dog 类继承 Animal 类
public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

// Cat 类继承 Animal 类
public class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

// 测试类
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog("旺财");
        Animal cat = new Cat("咪咪");

        dog.makeSound(); // 输出:汪汪汪
        cat.makeSound(); // 输出:喵喵喵
    }
}

5.多态的一些注意事项

1.如果加上了方法上了关键字 final 就不可以发生重写

2.如果是被stastic 修饰的方法也不可以发生重写

3.被private修饰的方法也不可以被重写

4.注意被除private修饰的方法,子类的权限范围大于父类的权限范围

5.不要把构造方法中方法重写

6.重写,建议加上@Override编译器就会检测是否符合重写的语法

四.结语

在我们之后的学习中,封装,继承,多态有着许多的运用用途,面对对象的三巨头还需要我们在具体的项目中你就会慢慢发现这其中的妙用。

感谢阅读

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/130912.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Apache Airflow (四) :Airflow 调度shell命令

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹…

Unity 制作血量滑动条(Slider)

1.创建UI slider 层级面板点击右键-UI-slider 2.调整UI位置 选择2D视图,调整锚点和滑动条位置 3.PS中制作UI 导出2个图层,PNG格式。 4.改成精灵模式(sprite2d) 把两个PNG导入Unity仓库中,选中两个图,右…

【LeetCode刷题笔记】堆和优先级队列

358. K 距离间隔重排字符串 解题思路: 大根堆 + 队列 , 1)首先 计数数组 统计 每个字符出现的次数 ,然后将 计数 > 0 的 字符 和 次数 一起放入 大根堆 ,大根堆中

Matlab的多项式留数与极点的计算

Matlab的多项式留数与极点的计算 以下面的多项式为例: 运算代码: clc clear closesyms p % 定义多项式 Zp(5*p^571*p^370*p)/(2*p^635*p^4117*p^236); % 提取分子与分母 [I,D]numden(Zp); Idouble(coeffs(I,p,"All"));%分子 Ddouble(coeffs…

Git系列之Git集成开发工具及git扩展使用

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的博客专栏《Git实战开发》。🎯🎯 &a…

基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(支持并行网关)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 这个章节来完成并行网关,前端无需修改,直接后端修改就可以了。 1、并行网关后端修…

C#开发的OpenRA游戏之世界存在的属性CombatDebugOverlay(3)

C#开发的OpenRA游戏之世界存在的属性CombatDebugOverlay(3) 这次来分析CombatDebugOverlay属性,这个属性只有在调试游戏的时候才会使用。当你设置这个属性的时候,就可以看到如下图的结果: 可以看到物品的周边都有一个圆圈,以及有一些十字的点位标志。 那些十字表示的点…

【ATTCK】MITRE Caldera 朴素贝叶斯规划器

CALDERA是一个由python语言编写的红蓝对抗工具(攻击模拟工具)。它是MITRE公司发起的一个研究项目,该工具的攻击流程是建立在ATT&CK攻击行为模型和知识库之上的,能够较真实地APT攻击行为模式。 通过CALDERA工具,安全…

C++源文件的编译过程 学习 CMake 文档的前置知识

OHHHH,发现自己的基础知识真他妈的是呼呼漏风,,,,,,,,,,, 尴尬得意识到,不仅是英语水平有问题,他码的基础知识…

Web实验总

目录 网站需求: 思路: 实验步骤: 第一步:准备工作 第二步:新建一个存储网页的目录 第三步:修改本地hosts映射 第四步:修改配置文件,建立基于http服务的网站 1)创建用户song和…

iOS移动应用安全加固:保护您的App免受恶意攻击的重要步骤

目录 iOS移动应用安全加固:保护您的App免受恶意攻击的重要步骤 摘要 引言 一、APP加固的概念 二、APP加固方案的比较 三、保护iOS应用的安全 四、总结 参考资料 摘要 本文介绍了移动应用程序(App)加固的概念和流程,以及市…

[模版总结] - 树的基本算法1 - 遍历

树结构定义 一种非线性存储结构,具有存储“一对多”关系的数据元素集合 种类 General Tree TrieB/B 树二叉树 满/完满/完全二叉树 完美BT : 除了叶子结点外所有节点都有两个字节点,每一层都完满填充完全BT: 除最后一层以外其他每一层都完美…

单元测试工具-Junit

文章目录 一. 认识Junit二. Junit中常用的注解1. Test2. Disabled3. BeforeAll & AfterAll4. BeforeEach & AfterEach 三. ParameterizedTest参数化1. 单参数2. 多参数2.1. CSV 获取参数2.2. 方法获取参数 四. Order控制测试用例的执行顺序五. 断言六. 测试套件1. 通过…

Docker进阶——再次认识docker的概念 Docker的结构 Docker镜像结构 镜像的构建方式

前言 在微服务大量应用的互联网时代,经常能看到docker的身影。作为docker的爱好者(在服务器安装MySQL,Redis。。。我用的都是docker),我也会持续深入学习和认识docker。 本篇博客再次介绍docker的基本概念&#xff0…

SmartBear正式收购Stoplight,并计划在核心API设计、文档和门户产品中集成其功能

不久前,软件开发和可视化工具提供商SmartBear正式宣布收购全球领先的API设计公司Stoplight。这一收购是为了打造业内最全面的API开发平台,为寻求现代化API实践的开发团队提供更好的透明度、自动化与生产力。将Stoplight在API方面的优势(包括治…

吴恩达《机器学习》7-1->7-4:过拟合问题、代价函数、线性回归的正则化、正则化的逻辑回归模型

一、过拟合的本质 过拟合是指模型在训练集上表现良好,但在新数据上的泛化能力较差。考虑到多项式回归的例子,我们可以通过几个模型的比较来理解过拟合的本质。 线性模型(欠拟合): 第一个模型是一个线性模型&#xff0…

Elasticsearch:Lucene 中引入标量量化

作者:BENJAMIN TRENT 我们如何将标量量化引入 Lucene。 Lucene 中的自动字节量化 虽然 HNSW 是一种强大而灵活的存储和搜索向量的方法,但它确实需要大量内存才能快速运行。 例如,查询 768 维的 1MM float32 向量大约需要 1,000,000*4*(7681…

多维时序 | MATLAB实现TCN时间卷积神经网络多变量时间序列预测

多维时序 | MATLAB实现TCN时间卷积神经网络多变量时间序列预测 目录 多维时序 | MATLAB实现TCN时间卷积神经网络多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现TCN时间卷积神经网络多变量时间序列预测 模型描述 MATLAB实现TCN时间卷…

3.前端调式(断点调式)

1. Elements 先来看这张图最上头的一行是一个功能菜单,每一个菜单都有它相应的功能和使用方法,依次从左往右来看 箭头按钮 用于在页面选择一个元素来审查和查看它的相关信息,当我们在Elements这个按钮页面下点击某个Dom元素时,箭…

ubuntu16.04安装vscode遇到的code 依赖于 libnss3 (>= 2:3.30)解决

1、ubuntu16.04安装最新版本vscode失败原因 ubuntu16.04安装最新版本的vscode会遇到依赖libnss3(>2:3.30)的问题,原因是ubuntu16.04安装的库libnss3版本更低,与vscode需要的更高版本的libnss3库不兼容,只需要升级libnss3库版本高于2:3.30…