前言:为什么要引入面向对象
边学边记 – OOP(Object Orientated Programing)
1. 为什么要引入面向对象? 原因:==封装、继承、多态==
1 2 举个例子理解面向对象代码的好处: 比如:我们有一个实际问题,假设现在一个宠物店有两只小狗, 第一只叫做小白,年龄2岁,白色;第二只叫做小红,年龄3岁,红色;现在我们的宠物店的系统可以让用户在输入不同狗的名字,能显示不同的狗的信息,如果没有,就输出该宠物店没有这条狗。
1.1 非面向对象 不使用面向对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package study;import java.util.Scanner;public class oobject1 { public static void main (String[] agrs) { String dogName = "小白" ; int dogAge = 2 ; String dogColor = "白色" ; String dogName1 = "小红" ; int dogAge1 = 2 ; String dogColor1 = "白色" ; Scanner scanner = new Scanner (System.in); System.out.println("请输入狗的名字:" ); String queryDogName = scanner.nextLine(); if (queryDogName.equals("小红" )){ System.out.println("狗名: " + dogName1 + "\n" + "狗龄: " + dogAge1 + "\n" + "颜色: " + dogColor1); }else if (queryDogName.equals("小白" )){ System.out.println("狗名: " + dogName + "\n" + "狗龄: " + dogAge + "\n" + "颜色: " + dogColor); }else { System.out.println("该宠物点没有这条狗" ); } } } class oobject2 { public static void main (String[] args) { String[] dogName = {"小白" ,"小红" }; int [] dogAge = {2 ,3 }; String[] dogColor = {"白色" ,"红色" }; System.out.println("请输入狗名:" ); Scanner s = new Scanner (System.in); String queryDogName = s.nextLine(); boolean flag = false ; for (int i=0 ;i<dogName.length;i++){ if (queryDogName.equals(dogName[i])){ System.out.println("狗名: " + dogName[i] + "\n" + "狗龄: " + dogAge[i] + "\n" + "颜色: " + dogColor[i]); flag = true ; } } if (!flag){ System.out.println("该宠物点没有这条狗" ); } } }
输出结果:
1.2 面向对象: 使用面向对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class oobject3 { private String dogName; private int dogAge; private String dogColor; public oobject3 (String dogName,int dogAge,String dogColor) { this .dogName = dogName; this .dogAge = dogAge; this .dogColor = dogColor; } public void getInfo () { System.out.println("狗名: " + dogName + "\n" + "狗龄: " + dogAge + "\n" + "颜色: " + dogColor); } public String getDogName () { return dogName; } public static void main (String[] args) { oobject3 whiteDog = new oobject3 ("小白" ,2 ,"白色" ); oobject3 reDog= new oobject3 ("小红" ,3 ,"红色" ); Scanner scanner = new Scanner (System.in); System.out.print("请输入狗的名字:" ); String queryDogName = scanner.nextLine(); if (queryDogName.equals(whiteDog.dogName)){ whiteDog.getInfo(); }else if (queryDogName.equals(reDog.dogName)){ reDog.getInfo(); }else { System.out.println("该宠物点没有这条狗" ); } } }
由上面两个例子,我们从代码的角度去看,为什么引入面向对象会更方便。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 当不使用面向对象的方式,采用数组或独立变量的方式进行编程时,每个“对象”(这里是指表示狗的信息)都需要通过独立的变量或数组元素进行定义。这意味着对于每一只狗,都需要单独声明和初始化相关的变量。当我们有成千上万个这种“对象”时,就需要重复定义更多的代码,这就会导致: 1 .冗余和代码膨胀:随着狗的数量的增加 ,代码中的相似的定义和初始化操作变得冗余。这导致了代码的膨胀,使得程序变得庞大且难以维护。2 .可读性很差: 大量的重复代码使得程序的可读性变差。维护人员很难在代码中找到并理解与每只狗相关的所有信息。3 .难以修改:如果我们要对狗的属性进行修改、或者添加新的属性,那么整个代码的维护更新就会非常难以进行,并且容易出错。4 .缺乏结构性:独立变量或数组元素的方式缺乏结构,不易于组织和管理相关的信息。随着信息的增加,代码可能变得混乱且难以理解。使用面向对象的好处主要体现在以下几个方面: 1 .封装和抽象: 面向对象编程强调封装,将对象的属性和行为封装在一起,提供了更高层次的抽象。这使得程序员可以专注于对象的接口,而不必关心内部的实现细节。这样的封装和抽象提高了代码的模块化和可维护性。2 .可维护性和可扩展性: 面向对象的编程模型使得代码更易于维护和扩展。通过创建类和对象,可以轻松地添加新的功能或修改现有功能,而不必改变整个程序的结构。这种灵活性使得程序更具可维护性和可扩展性。3 .代码重用: 面向对象的设计强调重用性。通过创建类和继承,可以在不同的地方重复使用相同的代码。这降低了重复编码的需求,提高了开发效率。4 .继承和多态: 继承和多态是面向对象编程的两个核心概念。继承允许创建一个类,继承另一个类的属性和方法,从而实现代码的重用。多态性允许同一个方法在不同的对象上表现出不同的行为,提高了代码的灵活性和可扩展性。更好的组织结构: 面向对象的设计强调将现实世界的问题映射到代码结构中。通过创建类和对象,能够更自然地模拟问题领域中的实体和关系,使得代码更易于理解和维护。 团队协作: 面向对象的设计使得多人协作更为容易。每个类可以被视为一个独立的模块,不同的团队成员可以独立地开发和测试各自负责的类。这有助于提高团队的生产力和协作效率。
所以在Java中引入面向对象,以及使用面向对象都是必要的。
2. 面向对象 VS 面向过程
这里假设面试官问你面向对象和面向过程的区别,我们怎么回答?(已经汗流浃背了 ~ )
2.1 语言 面向对象语言:
Java :毋庸置疑,Java一切皆对象,肯定是面向对象编程
C++ :一种支持 面向对象和面向过程编程的语言
C#(C Sharp): 由Microsoft开发,用于.NET平台,支持面向对象编程和其他现代编程概念。
Python : Python是一种多范式的编程语言,支持面向对象编程、面向过程编程以及函数式编程。
Ruby: 一种动态脚本语言,以其简洁而强大的面向对象特性而受欢迎。
Swift: 由Apple开发,专为iOS和macOS设计,具有现代化的面向对象特性。
Objective-C: 用于iOS和macOS的编程语言,支持面向对象编程。
面向过程语言:
C: 一种广泛使用的面向过程编程语言,以其效率和直接的硬件访问而受欢迎。
C++ :C++是一种多范式的编程语言,它既支持面向对象编程(具有类、继承等特性),也支持面向过程编程。在C++中,你可以采用纯粹的面向过程的编码风格,就像在C语言中一样。
Python : Python也是一种多范式的编程语言,支持面向对象编程、面向过程编程以及函数式编程。尽管Python提供了丰富的面向对象特性,但也允许开发者采用面向过程的编程风格。
Fortran: Fortran是一种主要用于科学和工程计算的编程语言,以其数值计算和面向过程的特性而著称。
2.2 OOP vs OPP
面向对象和面向过程的本质区别就是处理逻辑(思维模式)的不同。
1.面向过程的思维模式就是简单的线性思维,解决问题首先陷入第一步干什么、第二部干什么的细节中。这种思维模式适合处理一些简单的事务,别入从A走到B,把垃圾倒入垃圾桶等等。如果面对复杂的问题,那么解决就会很麻烦。
2.相反,面向对象更注重的是对问题的整体抽象和建模。它将问题中的实体抽象为一个个的对象,关注对象之间的交互。让对象去解决问题,这样的思维模式更加自然,更加贴近生活。
考虑一个复杂任务,比如设计并制造一艘航天飞船,面向过程的思维模式可能会让人感到困扰,因为这需要考虑众多细节和步骤。然而,通过面向对象的思维模式,我们可以将这个庞大的任务分解成对象,例如“引擎”、“控制系统”、“舱体”等,每个对象都有特定的属性和行为。这种抽象和分解使得我们能够更清晰地理解并解决问题,而不会被淹没在无尽的步骤中。
3.感受面向对象的美 我们直接使用代码去理解这个东西!!! 去感受为什么Java中的封装、继承、多态的好处
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package study;abstract class shape { private String color; public shape (String color) { this .color = color; } public String getColor () { return color; } public abstract double getArea () ; } class Circle extends shape { private double radius; public Circle (String color ,double radius) { super (color); this .radius = radius; } @Override public double getArea () { return Math.PI * Math.pow(radius,2 ); } } class Rectangle extends shape { private double len; private double width; public Rectangle (String color,double len , double width) { super (color); this .len = len; this .width = width; } @Override public double getArea () { return len * width; } } public class oobject2 { public static void main (String[] args) { Circle circle = new Circle ("Red" , 5.0 ); System.out.println("Circle Area: " + circle.getArea()); System.out.println("Circle Color: " + circle.getColor()); Rectangle rectangle = new Rectangle ("Blue" , 4.0 , 6.0 ); System.out.println("Rectangle Area: " + rectangle.getArea()); System.out.println("Rectangle Color: " + rectangle.getColor()); } }
上面的例子中,我们很清楚的可以看到Java中封装、继承、多态的好处。下面我在赘述一遍 ┭┮﹏┭┮
我们在抽象类 shape中将color属性被声明为私有(private),外部类无法直接访问。颜色的访问和设置通过公共方法getColor进行,这体现了封装的概念、隐藏类内部实现细节。
Circle 和 Rectangle 子类继承了 Shape 类,并通过调用 super(color) 访问了父类的构造方法,这也是一种封装的体现,子类不需要直接访问父类的私有属性。
1 2 3 4 封装的好处: 封装提高了代码的安全性:将属性声明为私有,通过公有方法进行访问,防止外部直接修改对象的内部状态值,从而提高数据的安全性。 封装隐藏细节:封装允许隐藏内部实现细节,使得使用者只需要关注对象的公有接口。这样的设计可以降低了系统的复杂性,是代码更容易理解和维护。 封装提高灵活性:如果内部实现需要更改,只需保持公有接口不变,使用者不受影响。这种灵活性使得系统更容易适应变化。
在 Circle 和 Rectangel 类都是通过关键字extends继承自shape 抽象类。这使得子类获得了父类的属性和方法,实现了代码的重用。例如:两个类都继承父类的color属性和getColor方法。
1 2 3 4 继承的好处: 代码重用: 继承允许子类重用父类的代码,避免了重复编写相似的代码,降低了代码的重复率。 可维护性: 当需要修改或扩展功能时,只需在父类中进行修改,子类将自动继承这些变化。这降低了修改代码的风险,提高了可维护性。 多态支持: 继承是实现多态的基础。通过继承,不同的子类可以被视为同一类型的对象,提供了更灵活的代码结构。
在 shape抽象类的抽象方法getArea中体现了多态。不同的子类分别重写了这个方法,根据自己的需求提供了具体的实现。在测试类中,通过统一的接口 getArea 调用,实际上调用了各个子类的实现,展现了多态性。
1 2 3 4 多态的好处: 灵活性和扩展性: 多态允许同一类型的对象以不同的方式响应相同的方法调用。这提高了代码的灵活性和可扩展性,使得系统更容易适应变化。 简化代码: 多态性允许使用者通过一个统一的接口调用不同类型的对象,简化了代码,提高了可读性。 实现抽象概念: 多态性使得我们能够以更抽象的方式思考和设计问题,将实际对象视为抽象概念的实例,有助于更清晰地理解和解决问题。