封装

把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。

通俗的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。

通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。但是如果⼀个类没有提供给外界访问的⽅法,那么这个类也没有什么意义了。

我们来看一个常见的 类,比如:Student

public class Student implements Serializable {private Long id;private String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
复制代码

将对象中的成员变量进行私有化,外部程序是无法访问的。对外提供了访问的方式,就是set和get方法。 而对于这样一个实体对象,外部程序只有赋值和获取值的权限,是无法对内部进行修改

继承

继承 就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。 在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

class 父类 {
}class 子类 extends 父类 {
}
复制代码

继承概念的实现方式有二类:实现继承接口继承

实现继承是指直接使用基类的属性和方法而无需额外编码的能力

接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力

一般我们继承基本类和抽象类用 extends 关键字,实现接口类的继承用 implements 关键字。

注意点:

通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。

继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。

子类可以拥有父类的属性和方法。

子类可以拥有自己的属性和方法, 即⼦类可以对⽗类进⾏扩展。

子类可以重写覆盖父类的方法。

JAVA 只支持单继承,即一个子类只允许有一个父类,但是可以实现多级继承,及子类拥有唯一的父类,而父类还可以再继承。

使用implements关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

# implements 关键字public interface A {public void eat();public void sleep();
}public interface B {public void show();
}public class C implements A,B {
}
复制代码

值得留意的是: 关于父类私有属性和私有方法的继承 的讨论 这个网上 有大量的争论,我这边以Java官方文档为准: With the use of the extends keyword, the subclasses will be able to inherit all the properties of the superclass except for the private properties of the superclass. 子类不能继承父类的私有属性(事实),但是如果子类中公有的方法影响到了父类私有属性,那么私有属性是能够被子类使用的。

官方文档 明确说明: private和final不被继承,但从内存的角度看的话:父类private属性是会存在于子类对象中的。

通过继承的方法(比如,public方法)可以访问到父类的private属性

如果子类中存在与父类private方法签名相同的方法,其实相当于覆盖

个人觉得文章里的一句话很赞,我们不可能完全继承父母的一切(如性格等),但是父母的一些无法继承的东西却仍会深刻的影响着我们。

多态

同一个行为具有多个不同表现形式或形态的能力就是 多态。网上的争论很多,笔者个人认同网上的这个观点:重载也是多态的一种表现,不过多态主要指运行时多态

Java 多态可以分为 重载式多态重写式多态:

-重载式多态,也叫编译时多态。编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的方法。通过编译之后会变成两个不同的方法,在运行时谈不上多态。也就是说这种多态再编译时已经确定好了。

-重写式多态,也叫运行时多态。运行时多态是动态的,主要指继承父类和实现接口时,可使用父类引用指向子类对象实现。这个就是大家通常所说的多态性

这种多态通过动态绑定(dynamic binding)技术来实现,是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。也就是说,只有程序运行起来,你才知道调用的是哪个子类的方法。 这种多态可通过函数的重写以及向上转型来实现。

多态存在的三个必要条件:

  1. 继承
  2. 重写
  3. 父类引用指向子类对象:Parent p = new Child();

我们一起来看个例子,仔细品读代码,就明白了:

@SpringBootTest
class Demo2021ApplicationTests {class Animal {public void eat(){System.out.println("动物吃饭!");}public void work(){System.out.println("动物可以帮助人类干活!");}}class Cat extends Animal {public void eat() {System.out.println("吃鱼");}public void sleep() {System.out.println("猫会睡懒觉");}}class Dog extends Animal {public void eat() {System.out.println("吃骨头");}}@Testvoid contextLoads() {//part1Cat cat_ = new Cat();cat_.eat();cat_.sleep();cat_.work();//part2Animal cat=new Cat();cat.eat();cat.work();cat.sleep();//此处编译会报错。Animal dog=new Dog();dog.eat();//结果为:吃骨头。此处调用子类的同名方法。//part3//如果想要调用父类中没有的方法,则要向下转型,这个非常像"强转"Cat cat222 = (Cat)cat;        // 向下转型(注意,如果是(Cat)dog 则会报错)cat222.sleep();        //结果为:猫会睡懒觉。 可以调用 Cat 的 sleep()}}
复制代码

我们来看上面part1部分:

Cat cat_ = new Cat();
cat_.eat();
cat_.sleep();
cat_.work();
复制代码

结果:

吃鱼 猫会睡懒觉。 动物可以帮助人类干活!

cat_.work(); 这处继承了父类Animal的方法,还是很好理解的 我们接着看part2:

Animal cat=new Cat();
cat.eat();
cat.work();
cat.sleep();//此处编译会报错。Animal dog=new Dog();
dog.eat();//结果为:吃骨头。此处调用子类的同名方法。
复制代码

这块就比较特殊了,我们一句句来看

Animal cat=new Cat(); 像这种这个 父类引用指向子类对象,这种现象叫做:“向上转型”,也被称为多态的引用

cat.sleep();这句 编译器会提示 编译报错。 表明:当我们当子类的对象作为父类的引用使用时,只能访问子类中和父类中都有的方法,而无法去访问子类中特有的方法

值得注意的是:向上转型是安全的。但是缺点是:一旦向上转型,子类会丢失的子类的扩展方法,其实就是 子类中原本特有的方法就不能再被调用了。所以cat.sleep()这句会编译报错。

cat.eat();这句的结果打印:吃鱼。程序这块调用我们Cat定义的方法。

cat.work();这句的结果打印:动物可以帮助人类干活! 我们上面Cat类没有定义work方法,但是却使用了父类的方法,这是不是很神奇。其实此处调的是父类的同名方法

Animal dog=new Dog();dog.eat();这句的结果打印为:吃骨头。此处调用子类的同名方法。

由此我们可以知道当发生向上转型,去调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。如果子类没有同名方法,会再次去调父类中的该方法

我们现在知道了 向上转型时会丢失子类的扩展方法,哎,但我们就是想找回来,这可咋办? 向下转型可以帮助我们,找回曾经失去的

我们来看part3:

    Cat cat_real = (Cat)cat;  //注意 此处的cat 对应上面父类Animal,可不是子类cat_real.sleep();
复制代码

Cat cat = (Cat)cat; cat222.sleep(); 这个向下转型非常像"强转"。

打印的结果:猫会睡懒觉。此处又能调用了 子类Cat 的 sleep()方法了。

一道简单的面试题

我们再来看一道有意思的题,来强化理解

public class Main {static class Animal{int weight = 10;public void print() {System.out.println("this Animal Print:" + weight);}public Animal() {print();}}static class Dog extends Animal {int weight = 20;@Overridepublic void print() {System.out.println("this Dog Print:" + weight);}public Dog() {print();}}public static void main(String[] args) {Dog dog = new Dog();System.out.println("---------------");Animal dog222 = new Dog();Dog dog333 =  (Dog)dog222;System.out.println("---------------");Dog dog444 = (Dog)new Animal();}
}
复制代码

执行结果:

this Dog Print:0 this Dog Print:20


this Dog Print:0

this Dog Print:20


this Animal Print:10 Exception in thread “main” java.lang.ClassCastException: com.zj.Main Animalcannotbecasttocom.zj.MainDog at com.zj.Main.main(Main.java:15)

做对了嘛,不对的话,复制代码去idea中debug看看 [图片上传失败…(image-f7f8e1-1666835336011)]

我们先看第一部分

Dog dog = new Dog();

程序内部的执行顺序:

  1. 先 初始化 父类Animal 的属性 int weight=10
  2. 然后 调用父类Animal的构造方法,执行print()
  3. 实际调用子类Dog的print()方法,打印:this Dog Print:0,由于此时的子类属性weight 并未初始化
  4. 初始化 子类Dog 的属性 int weight=20
  5. 调用 子类Dog的构造方法,执行print()
  6. 实际调用当前类的print()方法,打印this Dog Print:20

其中有几处我们需要注意一下:实例化子类dog,程序会去默认优先实例化父类,即子类实例化时会隐式传递Dog的this调用父类构造器进行初始化工作,这个和JVM的双亲委派机制有关,这里就不展开讲了,先挖个坑,以后再来填

面向对象编程三⼤特性 --封装、继承、多态相关推荐

  1. Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态

    Java 面向对象编程三大特性: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没有 ...

  2. python多态的三种表现形式_python小结----面向对象的三大特征(封装,继承,多态)

    面向对象的三大特征: 封装,继承,多态 面向对象的编程思想核心:高类聚,低耦合–程序的设计模式范畴 封装 什么是封装: 在面向对象编程的思想中,对代码进行高度封装,封装又叫包装 封装就是指将数据或者函 ...

  3. Python - 面向对象编程 - 三大特性之继承

    继承 继承也是面向对象编程三大特性之一 继承是类与类的一种关系 定义一个新的 class 时,可以从某个现有的 class 继承 新的 class 类就叫子类(Subclass) 被继承的类一般称为父 ...

  4. 【Java基础】 ⾯向对象编程三⼤特性 --封装、继承、多态

    文章目录 封装 继承 多态 封装 把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏.封装是面向对象的特征之一,是对象和类概念的主要特性. 通俗的说 ...

  5. 面向对象 编程及面向对象三大属性:封装 继承 多态

    面向对象 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构.应用平台.分布式系统.网络管理结构. ...

  6. 深入理解Java面向对象三大特性 封装 继承 多态

    1.封装 封装的定义: 首先是抽象,把事物抽象成一个类,其次才是封装,将事物拥有的属性和动作隐藏起来,只保留特定的方法与外界联系 为什么需要封装: 封装符合面向对象设计原则的第一条:单一性原则,一个类 ...

  7. Java面向对象三大特性(封装继承多态)解释及案例

    文章目录 包 包基本语法 命名规则 命名规范 导入包实例 访问修饰符 面向对象编程-封装 面向对象编程-继承 super关键词 super和this的比较 方法重写/覆盖 (override) 注意事 ...

  8. Python学习笔记④——类、面向对象的三大特征 [封装+继承+多态]

    ✅ Blogger Learns Python is for learning the "Deep Learning". 文章目录 一.面向对象编程的简介 二.类与对象 -- 基础 ...

  9. 面向对象的三特性(继承、多态、封装 )Python

    继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 class ParentCla ...

最新文章

  1. CNN的一些可视化方法!
  2. html如何与py_Web项目如何做单元测试?
  3. VTK:PolyData之TriangleArea
  4. HashCode和hashMap、hashTable
  5. oc51--循环retain
  6. freecodecamp_我在1个月内完成了整个freeCodeCamp课程(并记录了所有内容)
  7. 创意合成广告欣赏:让人脑洞大开的设计
  8. jq获得当前元素id
  9. JS学习总结(5)——循环语句
  10. 简单谈谈MySQL优化利器-慢查询
  11. SC2disease:人类疾病的单细胞转录组的人工收集数据库
  12. 遍历Map集合的4种常用方法
  13. php 利用gd库及tcpdf 自动多图片生成pdf
  14. EtherCAT协议基础知识(Part 3)
  15. 对于复杂网络解决现实的网络问题
  16. drcom linux最新版,Ubuntu高于8.04版本的源码安装drcom
  17. Pandas入门超详细教程,看了超简单
  18. 线程三连鞭之“线程基础”
  19. SSM框架的基本概念(什么是ssm框架?)
  20. Workbook类提供的方法

热门文章

  1. 「mysql是怎样运行的」第19章 从猫爷被杀说起---事务简介
  2. 在Q版人物设计时忌讳复杂的语言
  3. Python代码画发射爱心-Turtle绘图
  4. 六级(2021/6-1) Text1
  5. Mac系统远程桌面--Windows电脑远程控制Mac系统
  6. 网络映射服务器共享盘无反映,网络映射盘连接不上
  7. k8s dial tcp connect: no route to host
  8. 文献调研-词云图的制作
  9. 扫描件怎么转换成pdf文档?快来了解下手机扫描的方法
  10. Ubuntu11.10耳机没声音?解决之...