ObjectOrientedProgramming - 面向对象的编程(包、继承、多态的一部分:向下/向下转型,重写) -Java

x33g5p2x  于2021-11-22 转载在 Java  
字(4.6k)|赞(0)|评价(0)|浏览(428)

包 (package) 是组织类的一种方式.

  1. 包里存的基本上都是类,而这些类都是别人写好的。我们只需要拿着用。前提是导入对应的包

代码案例(打印数组):

  1. import java.util.Arrays;// 导入包util包中的 Arrays 类, 图 1
  2. public class ObjectOrientedProgramming {
  3. public static void main(String[] args) {
  4. int[] array = {1,2,3,4,5};
  5. System.out.println(Arrays.toString(array));
  6. 在输入 Arrays 的途中,编译器会给出提示,只要我们选择就能自动导入对应包中的类。
  7. // Arrays 是一个类,而toString 由类 来调用的,说明toString 是一个静态方法 (图2)
  8. // 也就是说所有通过类调用的方法都是 静态的
  9. }
  10. }
附图(缺少的那句代码,作用就是导入一个包。从包中拿出你需要的类)

图1

图2

经由上面一个简单的程序附图2,引申出一格问题: 什么是 package 和 import?

  1. package (包)
  2. 指:类所在的包
  3. import (引入包中的类)
  4. 引入在类中需要的类(我们写的程序就是一个类,import 的作用就是 在我们写程序的时候, 引入我们所需要的类)

在java里,包肯定不止一个,那么就意味着 一个 类,可能有在不同包里都有它,只不过实现的功能不同。选择对应包中的类,编译器会自动帮你导入所需包中的类

例1

例2

既然知道包是怎么导入它当中的类,那么该如何使用? new它!

实例1(导入(包中的类)情况)

实例2(不导入(包中的类)情况)

前者都是导入包中的类,在程序中就可以使用该类。那我们只导入包呢?在程序中我们还可以使用它里面的类吗?

由结果得知: 不能,在Java中 只能导入一个具体的类,不能带入一个具体的包。

我们再来看看 用特殊的方法 导入一个类

  1. import java.util.*; // * 在该代码中 表达的意识是 通配符。
  2. 这么写是什么意思?
  3. 导入这个包里所有类。

示例

疑问:util包中 有很多类,难道 “ impor java.util.*; ” 是一下子全部 都导入吗?

  1. 不是的,Java 处理的时候,需要哪个类,它才会给你那个类。
  2. 就是说:Java不会提前给你任何类,当你需要某个类的时候,再给你。而且是要一个,给一个。
  3. 不会说要一个,给你一大堆。
  4. 这也是 Java C 的区别之一。
  5. 假设 include<stdio.h>
  6. C 通过 include 关键字,将 stdio.h 头文件里面的内容全部都拿过来,导入程序。
  7. 这就好比 古时 朝廷 发赈灾款 某位大臣,这批钱,你怎么用都行。
  8. 而不是 先排大臣过去,碰到一项需要开支的地方,再向朝廷申请 合适的 拨款数目
  9. 如果你要问:Java C 那个导入方式好,肯定是java。因为 Java 是用一个,给一个,用不到的,绝对不会给你。省空间。
  10. 不像C一样,一股脑的全给你,管你用不用,这样就会造成空间的浪费,

那么 “ impor java.util.*; ” 和 “ impor java.util.具体的类名; ” ,那个更好?

  1. impor java.util.具体的类名; 更好!

拿 前面 例子中 Date 举例,

由图我们发现 Date这个类, 在很多包中 都有。如果我们 同时使用两个包中的Date,且使用 通配符的导入模式。会怎么样?

import static - 静态导入

  1. 使用 import static 可以导入包中的 静态的 方法 字段
  2. 方法:
  3. import static java.lang.具体的类.*;

实例

但是这种方法用的不多,虽然代码简单,但是阅读性不高。不建议这么写。(了解)

使用包的主要目的是保证类的唯一性

但是 如果一个项目很大,有50多人参与这个项目,有可能会出现 类名相同的情况。
此时包的作用就体现出来了。

在此之前,我们先来看包是如何创建的(包名 必须小写)

把类放进包里

  1. 方法:
  2. 和我们平常在src目录下,新建clas文件(类)一样,直接反键new就行了。

使用我们自己创建的包中的类

包的访问权限控制

  1. 我们已经了解了类中的 public private. private 中的成员只能被类的内部使用.
  2. 如果某个成员变量不包含 public private 关键字(不加任何的访问修饰限定词的时候), 这个成员变量就具有包的的权限,
  3. 此时这个成员变量可以在包内部的其他类使用, 但是不能在包外部的类使用该成员变量

常见的包(系统包)

  1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2. java.lang.reflect:java 反射编程包;
  3. java.net:进行网络编程开发包。
  4. java.sql:进行数据库开发的支持包。
  5. java.util:是java提供的工具程序包。(集合类等) 非常重要
  6. java.io:I/O编程开发包。

面向对象的基本特征:

封装:不必要公开的数据成员和方法,使用private关键字进行修饰。意义:安全性。

继承:对共性的抽取。使用extends关键字进行处理的。 意义:可以对代码进行重复使用。

先来通过代码了解一些知识点,为了我们了解继承做铺垫

讲这些共有的特性抽离出来

继承的语法规则

基本语法

  1. class 子类 extends 父类 {
  2. }

总结

使用 extends 指定父类.
子类会继承父类的所有 public 的字段和方法.
Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承).

对于父类的 private 的字段和方法, 子类中是无法访问的.

子类构造的同时,要 帮助父类来进行构造

super关键字的用法,this的用法可以看这篇文章 类与对象

·子类继承父类,子类在内存中的情况

特殊情况 ( 子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用 )

相当于 上图 wing,是鸟类自带的属性。不会被父类的构造方法的初始化所影响。

protected 关键字

  1. 刚才我们发现, 如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 "封装" 的初衷.
  2. 两全其美的办法就是 protected 关键字.
  3. 对于类的调用者来说, protected 修饰的字段和方法是不能访问的
  4. 对于类的 子类 同一个包的其他类 来说, protected 修饰的字段和方法是可以访问的

访问权限图( private | default | protected | public)

No范围privatedefault(包权限)protectedpublic
1同一个包中的同类okokokok
2同一个包中的不同类nookokok
3不同包中的子类nonookok
4不同包中的非子类nononook

private: 类内部能访问, 类外部不能访问
默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
public : 类内部和类的调用者都能访问

同一个包中的同一个类

同一个包中的不同类

不同包的子类(类的继承需要两个类都是public的类)

不同包的非子类

上面这些情况中,调用的成员变量都是有public修饰的,也就是说 只要我们 字段/属性/成员变量是被public 所修饰的,就意味着在哪里都能使用。

我们主要还是讲 protected,因为其他的,在前面都讲了。

同一个包中的同一个类

同一个包中的不同类

不同包的子类(前面protected 和 public几乎一样,但下面两点就是public 和 protected 的区别)

不同包的非子类

总结

  1. protected 的出现为了防止继承的时候,非子类也能调用父类当中成员变量和方法,
  2. 让父类数据,不会被随意调用,造成不可预料的效果。(就好比我举的例子,狗和鸟,狗不会飞,但是你让狗去继承鸟的翅膀,可能吗?)
  3. protected 还有一个,一个好处: 即使不同类不同包,只要是子类,就可以去调用父类的数据
  4. 时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一
  5. 系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.
  6. 但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了 .
  7. 如果一个类不想被继承, 就可以使用 final 关键字.对其进行修饰

final 关键字

  1. 曾经我们学习过 final 关键字, 修饰一个变量或者字段的时候, 表示 常量 (不能修改)
  2. 现在拓展一下:
  3. final 关键字也能修饰类, 此时表示被修饰的类就不能被继承.

final 关键字的功能是 限制 类被继承
“限制” 这件事情意味着 “不灵活”. 在编程中, 灵活往往不见得是一件好事. 灵活可能意味着更容易出错.
是用 final 修饰的类被继承的时候, 就会编译报错, 此时就可以提示我们这样的继承是有悖这个类设计的初衷的.

组合

  1. 和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果
  2. 你可以理解为 a part of 一部分
  3. 例如:
  4. 学生 老师 学校的一部分
  5. 组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段.
  6. 这是我们设计类的一种常用方式之一.
  7. 组合表示 has - a 语义 the school hava students and teachers
  8. 在刚才的例子中, 我们可以理解成一个学校中 "包含" 若干学生和教师.
  9. 继承表示 is - a 语义 dog is animal
  10. 在上面的 "动物和猫" 的例子中, 我们可以理解成一只猫也 "是" 一种动物

多态 - 这里 只是铺垫,开个头,讲一个部分。

  1. 字面上理解: 语文层次: 一种食物多种形态。 但是这句话不要跟面试官,直接gg,这里只是 让你对多态先有个初步了解。

向上转型:

  1. 子类对象 父类 引用

什么情况下会发生向上转型?

1. 直接赋值

2. 函数的参数

3.作为函数的返回值

动态绑定(多态的基础)

当子类和父类中出现同名方法的时候, 再去调用会出现什么情况呢?

动态绑定的条件:

1.父类 引用 子类的对象
2.通过父类这个引用 调用 父类 和 子类 同名的覆盖(重写) 方法

重写 /覆盖 / 覆写

1.方法名相同
2. 参数的 个数 和 类型 相同
3. 最好返回值相同(协变类型:返回值可以不同。返回值的关系为父子类关系)
4. 父子类的关系

代码1

代码2 (动态绑定)

再来通过以下图片 来进一步了解 多态绑定

重写的注意事项

方法不可以是 static 方法

子类的访问修饰限定的访问范围一定要大于等于 父类 的 访问修饰限定

  1. 重写中子类的方法的访问权限 不能低于 父类的方法访问权限

private 方法 不能被重写

方法 被 final修饰 ,也不能被重写

方法的返回值不一样,也能被重写( 协变类型 )

特殊情况

重写 与 重载的区别

重载可 通过这篇文章进行参考方法的使用

1.方法名相同
2. 参数的 个数 和 类型 必须有一个不同(重写:参数的类型和个数都相同)
3. 返回值可以不同 (重写:协变类型可以返回值不同,一般情况返回值是一样)
4. 重载涉及静态绑定(重写:动态绑定)

编译时多态:利用重载来实现多态,在同一个类中定语多个同名的不同方法来实现多态

向下转型

  1. 向上转型: 父类引用 引用 子类对象
  2. 那么向下转型:子类引用 引用 父类对象
  3. 你可以这么去理解:父类 引用子类对象,子类b格提升。称为向上转型
  4. 子类 引用 父类 ,父类b格降级,称为向下转型

但是不建议大家去写 向下转型!

处理方法

再介绍一个坑(在构造方法中调用重写的方法)

本文结束

相关文章

最新文章

更多

目录