Java 面向对象的三个特性和五个基本原则
  anLrwkgbyYZS 2023年12月30日 11 0


面向对象(OOP)的三个特性: 封装性(Encapsulation),继承性和多态性。

面向对象(OOP)的五个原则: 单一职责原则(SRP)、开放封闭原则(OCP)、里氏替换原则(LSP)、依赖倒置原则(DIP)、接口隔离原则(ISP)。

1.  面向对象的三个特性

面向对象的三个特性: 封装性(Encapsulation),继承性和多态性。

1.1 封装性

封装性:将数据和对数据的操作封装起来,对象状态(属性)由这个对象自己的行为(方法)来读取和改变,隐藏细节部分。

Java 中 属性的封装,无特殊情况都是用的 private 修饰符, 用 private 修饰符声明该属性为私有属性,只允许类的内部直接访问该属性。对于私有属性,要给一对 setter() 和 getter() 方法操作,外部访问私有属性需要通过setter() 和 getter() 方法。 setter() 和 getter() 方法 IDE(idea、eclipse) 可快速生成 。

在类中可以使用 this 关键字访问本类的私有属性,this 关键字只能用于类的方法体中。如this.id,去访问本类的私有属性 id。

良好的封装能够减少耦合;保证属性的操作安全性。 

访问权限修饰符还有如下几种:

访问修饰符

同一个类

同一个包

不同包中的子类

工程的任意位置

private

可访问

 

 

 

缺省(default)

可访问

可访问

 

 

protected

可访问

可访问

可访问

 

public

可访问

可访问

可访问

可访问

1.2 继承性

继承性: 把多种有着共同特性的多的类事物抽象成一个类,这个类就是多个类的父类。父类的意义在于可以抽取多个类的共性,代码复用,减少代码量。

例:三个类,Pupil类(小学生),MiddleSchoolStudent类(中学生类),CollegeStudent类(大学生类),他们有一个特性,都要有名字,学号,班级等等属性,都要去上课,考试等行为。

我们可以写一个父类 为 student类(学生),在Student类中实现名字,学号,班级等属性,上课,考试等行为,Pupil类、 MiddleSchoolStudent类、CollegeStudent类 继承 Student 类之后,就不需要自己去实现这些方法,可以直接去访问父类的。上课这个方法你本来要写三遍,继承之后你只用实现一次, 就实现了代码复用,减少代码量。 

Java 只能单继承 ,即一个类只能有一个父类(A继承B之后,不能在继承其他的类);可以多层继承(A继承B,B继承C);多个类继承一个类(B和C都继承A)。

子类继承的关键字:extends。 A 类  extends B 类,A是B的子类,B是A的父类。

子类可以访问父类的 public 和 protected成员,四种访问属性在和子类中的含义如下。

父类成员访问属性

在父类中的含义

在子类中的含义

public

对所有人开放

对所有人开放

protected

只有包内其它类、自己和子类可以访问

只有包内其它类、自己和子类可以访问

缺省(default)

只有包内其它类可以访问

如果子类与父类在同一个包内:只有包内其它类可以访问

否则:相当于private,不能访问

private

只有自己可以访问

不能访问

继承的缺点:提高了类之间的耦合性。

1.3 多态性

多态性: 程序中定义的引用变量 “所指向的具体类型” 和 “通过该引用变量发出的方法调用” 在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。

静态多态(编译时多态):方法的重载实现 。重载:方法名相同,方法参数个数和类型不同

动态多态(运行时多态): 子类中对父类方法的重写、接口、抽象类和抽象方法。

接下来举几个动态多态的例子。

1.3.1  子类中对父类方法的重写

父类为 Student , 子类为 pupil 。

 Student.java :

package duotai;

public class Student {
    public void play() {
        System.out.println("play");
    }
}

 pupil.java :

package duotai;

public class Pupil extends Student{
    public void play() {
        System.out.println("唱儿歌");
    }
    public static void main(String args[]) {
        Student student = new Student();
        Pupil pupil = new Pupil();
        Student student1 = new Pupil();
        student.play();
        pupil.play();
        student1.play();
    }
}

执行   pupil.java 中的 main 方法,运行截图如下:

Java 面向对象的三个特性和五个基本原则_子类

1.3.2  接口实现多态

List 接口的两个实现类,ArrayList,LinkedList。

public class ListStudy {
    public static void main(String args[]) {
        List<String> list = new ArrayList<>();
        List<String> list1 = new LinkedList<>();
    }
}

2. 面向对象的五个基本原则

2.1 单一职责原则(SRP)

一个类应该只有一项工作。

比如在职员类里,将工程师、销售人员、销售经理这些情况都放在职员类里考虑,其结果将会非常混乱,在这个假设下,职员类里的每个方法都要if else判断是哪种情况,从类结构上来说将会十分臃肿,并且上述三种的职员类型,不论哪一种发生需求变化,都会改变职员类!这个是大家所不愿意看到的!

2.2 开放封闭原则(OCP)

对象或实体应该对扩展开放,对修改封闭。

更改封闭即是在我们对模块进行扩展时,勿需对源有程序代码和DLL进行修改或重新编译文件!这个原则对我们在设计类的时候很有帮助,坚持这个原则就必须尽量考虑接口封装,抽象机制和多态技术!

2.3 里氏替换原则(LSP)

子类可以替换父类并且出现在父类能够出现的任何地方,这个原则也是在贯彻GOF倡导的面向接口编程!

在这个原则中父类应该尽量使用抽象类和接口。

2.4 依赖倒置原则(DIP)

高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。具体实现应该依赖于抽象,而不是抽象依赖于实现。

可以这样理解,上面我举例子的时候先说了兔子和绵羊,然后才推出食草动物。但如果我们继续认识了牛、马等食草动物,我们会发现我们需要不断调整食草动物的描述,这样程序会变得僵化,所以我们不应该让子类依赖于实体,不应该让父类模块依赖于子类模块。所以我们需要将食草动物设计为抽象类,即抽象类或接口。这样下层只需要实现相应的细节而不会影响父类。

2.5 接口隔离原则(ISP)

不应强迫客户端实现一个它用不上的接口,或是说客户端不应该被迫依赖它们不使用的方法,使用多个专门的接口比使用单个接口要好的多!

比如,为了减少接口的定义,将许多类似的方法都放在一个接口中,最后会发现,维护和实现接口的时候花了太多精力,而接口所定义的操作相当于对客户端的一种承诺,这种承诺当然是越少越好,越精练越好,过多的承诺带来的就是你的大量精力和时间去维护!

参考文献:

  • 面向对象程序设计——Java语言网课课件 - 翁恺 - 浙江大学 
  • Java 程序开发案例课堂 - 刘春茂、李琪 - 清华大学出版社
  • 菜鸟教程 - Java 教程
  • Java2 实用教程 - 耿祥义、张跃平 - 清华大学出版社


 

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月30日 0

暂无评论

anLrwkgbyYZS
最新推荐 更多