面向对象(二)

面向对象(二)

一、封装

将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问

(1) 特点

①. 良好的封装能够减少耦合
②. 类内部的结构可以自由修改
③. 可以对成员变量进行更精确的控制
④. 隐藏信息,实现细节

(2) 访问控制符

Java提供了private、protected、public和不加任何访问控制符(default)4个访问控制级别

  private(当前类访问权限):如果用于修饰类里的一个成员(包括成员变量、方法和构造器等),该成员只能在当前类的内部被访问。   default(包(package)访问权限):如果用于修饰类里的一个成员(包括成员变量、方法和构造器等)或者一个外部类,该成员可以被相同包下的其他类访问。   protected(子类访问权限):如果用于修饰一个成员(包括成员变量、方法和构造器等),该成员既可以被同一个包中的其他类访问,也可以被不同包中的子类访问。在通常情况下,如果使用protected来修饰一个方法,通常是希望其子类来重写这个方法。   public(公共访问权限):如果用于修饰一个成员(包括成员变量、方法和构造器等)或者一个外部类,该成员或外部类就可以被所有类访问,不管访问类和被访问类是否处于同一个包中,是否具有父子继承关系。

访问控制级别

privatedefaultprotectedpublic
同一个类
同一个包
子类中
全局范围

(3) package(包)

包这种机制是为了防止命名冲突,访问控制,提供搜索和定位类、接口、枚举和注释等。

作用:
① 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
② 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
③ 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类

语法:package 包名;

一般在Java源程序的第一个非注释行(Java源文件的第一行)

导包操作:import 包名.子包名.类名(导入某个类)
     Import 包名.子包名.*(导入某个包下的所有类)

• 封装要点:
• 类的属性的处理:
  • 一般使用private. (除非本属性确定会让子类继承)
  • 提供相应的get/set方法来访问相关属性. 这些方法通常是public,从而提供对属性的读取操作。
  (注意:boolean变量的get方法是用:is开头!)
• 一些只用于本类的辅助性方法可以用private
• 希望其他类调用的方法用public

二、继承

继承机制是面向对象程序设计为了能够提高软件开发效率的技术,继承机制允许和鼓励类的重用,子类既具有自己新定义的属性和行为,又具有从父类继承下来的属性和行为。

Java的继承是通过extends关键字来实现的,实现继承的类被称为子类,被继承的类被称为父类。

###(1) 语法

  修饰符 class 父类{
  //父类类结构部分
  }

  修饰符 class 子类 extends 父类{
  //子类类结构部分
  }

(2) 继承的利弊

继承的好处:
  ① 提高了代码的复用性
  ② 提高了代码的维护性
  ③ 让类与类之间产生了关系,是多态的前提
继承的弊端:
  ① 类的耦合性增强了。

开发的原则:高内聚,低耦合。
* 耦合:类与类的关系
* 内聚:就是自己完成某件事情的能力

(3) 继承的特点

① Java只支持单继承(一个儿子只能有一个老爸)
② Java支持多层继承

③ 子类可以继承父类非 private 的属性、方法,但不能继承父类的构造器,(可以通过super关键字去访问父类的构造器)。子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。子类可以用自己的方式实现父类的方法,但父类不能实现子类特有的方法。
④ 使用原则:符合”is-a”原则(D is a B——D是B的子类)

(4) this与super

this:代表当前对象的引用,谁调用this,就代表谁
super:代表当前对象的父类的引用

this和super的使用区别
① 调用成员变量
  this.成员变量 调用本类的成员变量,也可以调用父类的成员变量(其实也是本类的成员变量,只不过是从父类继承过来的)
super.成员变量 调用父类的成员变量
② 调用构造方法
  this(…) 调用本类的构造方法
  super(…) 调用父类的构造方法
③ 调用成员方法
  this.成员方法 调用本类的成员方法,也可以调用父类的方法(其实也是本类的成员方法,只不过是从父类继承过来的)
  super.成员方法 调用父类的成员方法

注意: 子类所有构造器默认都会访问父类中无参构造(super()语句是隐藏的),因为子类会继承父类的数据,还会有可能使用父类的数据。所以子类初始化前需要先完成父类数据的初始化。

如果父类没有无参构造,可通过this或super解决,但this(…)或super(…)必须出现构造器的第一条语句中,且二者不能共存。

总结:父类最好手动的添加无参构造,如果需要调用父类的东西,再去通过super去调用。

(5) 方法重写(overwrite)——两同两小一大

两同:子类与父类中,方法名相同、形参列表相同。
两小:子类的方法返回值类型比父类方法返回值类型更小或相等
   子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等。
一大:子类方法的访问权限比父类方法的访问权限更大或相等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Curr{
public void fun(int i) {
System.out.println("int");
}
public void fun(int i,String s){
System.out.println("int,String");
}
public void fun(String s,int i){
System.out.println("String,int");
}
}

class override{
public static void main(String[] args) {
Curr curr = new Curr();
curr.fun(0);
curr.fun(0, "");
curr.fun("", 0);
}
}

应用:当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
注意:父类中私有方法不能被重写 子类重写父类方法时,访问权限不能更低

三、多态

同一个行为具有多个不同表现形式或形态的能力

  Java引用变量有两种类型:编译时类型(左边),运行时类型(右边)。如果编译时类型与运行时类型不一致,就会出现多态。

(1) 特点

① 消除类型之间的耦合关系
② 可替换性
③ 可扩充性
④ 接口性
⑤ 灵活性
⑥ 简化性

(2) 必要条件

① 要有继承关系。
② 要有方法重写。
③ 要有父类引用指向子类对象

(3) 多态中的访问特点之成员变量

编译看左边(父类),运行看左边(父类)
通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,而不是它运行时类型所定义的成员变量。(成员变量时前期编译时绑定的)

(4) 多态中的访问特点之方法

编译看左边(父类),运行看右边(子类)
编译时如果不写对应的方法会编译会报错,引用变量在编译阶段只能调用其编译类型所具有的方法,但运行时则执行它运行类型所具有的方法。(普通方法是动态绑定)

(5) 多态中的向上转型和向下转型

基本数据类型只能在数值类型(整数型、字符型和浮点型)之间进行
引用数据类型之间只能在具有继承关系的两个类型之间进行,如果两个没有任何继承关系的类型,无法进行类型转换。如果试图把一个父类实例转换成子类类型,则这个对象必须实际上是子类实例,否则会出现ClassCastException异常。

(6) 多态的利弊

好处:
提高代码的维护(继承保证)——父类有变化子类也随之变化
提高代码的扩展性(多态保证)
弊端:
不能使用子类的特有属性

(7) instanceof运算符

语法:对象名 instanceof 类
   B b = new B();
在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
为了防止ClassCastException,利用instanceof判断前面的引用是否属于后面的数据类型,如果是可以利用强制类型转换
运算符是双目运算符,左面的操作元是一个对象,右面是一个类.当左面的对象是右面的类创建的对象时,该运算符运算的结果是true,否则是false

文章作者: Hai
文章链接: http://yoursite.com/2019/07/14/面向对象(二)/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hai
打赏
  • 微信
  • 支付宝