作为一名从C语言开始起家的蒟蒻来说,C语言是面向过程编程,Java是面向对象编程,两个其实有着本质上的区别。本蒟蒻对于Java有一些个人的理解和看法,如果有错误请各位大佬指正!当然,我们学各种编程的最终目的都是买车买房实现财富自由,然后辞职躺平。那我们就用财富自由后开了一个汽车厂来举例吧!
华丽丽的分割线
以下是正文
开汽车厂得有轮胎,所以我们先找一家生产轮胎的厂家设计一款轮胎的流水线(这就好比是类的出厂设置):
public class 轮胎厂 {// 成员变量private String 型号;private int 使用年龄;// 构造方法(从类外部调用该类时,参数作为类的输入)public 轮胎厂(String 型号, int 使用年龄) {this.型号 = 型号;this.使用年龄 = 使用年龄;}// 成员方法(供外部调用该类,返回类的值)public String get型号() {return 型号;}public int get使用年龄() {return 使用年龄;}
}
一辆车需要多个轮胎,而轮胎的基本样式相差不大,所以可以直接从轮胎厂家购买轮胎用于汽车生产:
轮胎厂 轮胎前 1 = new 轮胎厂("A", 5);
轮胎厂 轮胎前 2 = new 轮胎厂("A", 2); // 假如爆过胎所以换了一个,使用年数比较少
轮胎厂 轮胎后 1 = new 轮胎厂("A", 5);
轮胎厂 轮胎后 2 = new 轮胎厂("A", 5);
以上是面向对象编程的基础,厂中生产轮胎的类型就如同java中的类,买来装在车上的轮胎就是java中的对象。类是面向对象编程的基石,它是一种模板或者蓝图,用于创建对象。而对象是类的实例。
厂家生产的轮胎,其型号和使用年龄可不能随意被他人修改,不然会出现轮胎与车辆不匹配或者以旧充新的问题。不过,当需要维修更新数据时,又不能无法修改。
这就涉及到了数据保护和代码的可维护性,也就是封装。封装的目的是将对象的属性和方法整合在一起,为对象的内部数据提供保护。在 Java 中,我们通过访问修饰符(如 private、public、protected)来实现封装。
在轮胎类中,我们把型号和使用年龄变量设为 private,这就意味着它们只能在类的内部被访问。外部代码无法直接修改这些变量,必须通过类提供的公共方法(如 get 型号和 get 使用年龄)来获取它们的值。
后来,你的汽车厂规模不断扩大,实现了一个小目标,那一个轮胎厂生产的轮胎不够你的汽车厂使用的,所以你又找到了一个轮胎厂希望可以一起生产,但是又不需要重新设计轮胎,直接把之前厂家的流水线继承过来就行(不考虑什么专利之类的现实问题)。
public class 轮胎厂 2 extends 轮胎厂 {private int 轮胎厂 Id;public 轮胎厂 2(String 型号, int 使用年龄, int 轮胎厂 Id) {super(型号, 使用年龄);this.轮胎厂 Id = 轮胎厂 Id;}public int get轮胎厂 Id() {return 轮胎厂 Id;}
}
这体现了 Java 中一个重要的概念 —— 继承。继承是面向对象编程中实现代码复用的关键机制。它允许我们创建一个新的类(子类),从已有的类(父类)中继承属性和方法。
在轮胎厂 2 类中,它继承了轮胎厂类的型号和使用年龄属性以及相关方法,同时还有自己的属性轮胎厂 Id。通过 super 关键字,我们可以在子类的构造方法中调用父类的构造方法来初始化继承的属性。继承使得代码更加简洁且易于维护。如果多个类有相似的属性和方法,我们可以把这些共同部分提取到一个父类中,让其他类继承这个父类。
轮胎厂 2 继承了轮胎厂的流水线,但两个厂商生产的轮胎需要打上不同的标签来区分。
public class 轮胎厂 {//...public void 标签() {System.out.println("型号: " + 型号 + "\n 使用年龄: " + 使用年龄);}
}public class 轮胎厂 2 extends 轮胎厂 {//...@Overridepublic void 标签() {System.out.println("型号: " + 型号 + "\n 使用年龄:" + 使用年龄 + "\n 轮胎厂 Id: " + 轮胎厂 Id);}
}
这就是方法重写,方法重写发生在子类中,当子类想要提供一个与父类中已有的方法具有相同签名(方法名、参数列表、返回类型相同或兼容)的方法时,当我们在轮胎厂 2 对象上调用标签方法时,执行的是轮胎厂 2 类中重写后的版本。
你的汽车厂不仅有卖车业务,还推出了汽车保养服务,不过不同的车保养的数值不一样(原谅我找不到更合适的例子了)。
public class 汽车保养 {public int 维修(int 磨损程度, int 保养效果) {return 保养效果 - 磨损程度;}public double 维修(double 磨损程度, double 保养效果) {return 保养效果 - 磨损程度;}
}
这就是方法重载。方法重载是在同一个类中,存在多个方法具有相同的方法名,但参数列表不同(参数个数、类型或顺序不同)。
方法重写(Overriding)和方法重载(Overloading)都属于多态的范畴。多态是面向对象编程中另一个重要的概念,它允许不同的类对象对同一消息做出不同的响应。通过多态,我们能够编写更灵活、可扩展的代码。不同的对象可以依据自身类型执行特定的行为,而调用代码无需知晓具体对象的类型。
那么,回到最初的问题,Java 和 C 语言的区别究竟在哪里呢?还是用汽车的例子来说明,这次假设你要开车上高速,在此之前需要对车辆进行保养和检查。
面向对象编程就像是你把汽车送到 4S 店进行保养,你只需查看最终的检查报告单信息就行,此时汽车被当作一个整体对象。
面向过程编程则是你自己对汽车进行检查,需要一步一步地测量胎压,按照步骤逐个检查各项数值。
面向过程编程(Procedural Programming):是一种以过程(或函数)为中心的编程范式。它强调的是程序的执行流程,将一个复杂的问题分解为一系列的步骤,通过函数来实现这些步骤,然后按照一定的顺序调用这些函数来解决问题。在这种范式中,数据通常是全局的或者通过参数在函数之间传递。
面向对象编程(Object - Oriented Programming):是以对象为中心的编程范式。它将数据和操作数据的方法封装在一起,形成对象。对象是现实世界中事物的抽象,具有自己的属性(数据)和行为(方法)。通过对象之间的交互来完成程序的功能,并且强调代码的复用性、可维护性和可扩展性,通过继承、多态等特性来实现这些目标。
C 语言没有像 Java 那样的类(class)的概念来封装数据和方法。虽然可以通过结构体(struct)来组合数据,但没有内置的机制将函数和结构体紧密地绑定在一起作为一个对象的概念。例如,在 C 语言中,没有继承、多态这些面向对象编程中用于代码复用和行为多态性的特性。虽然可以通过函数指针等方式模拟多态的某些行为,但这与面向对象语言中天然的多态机制相比,实现起来更加复杂和不直观。
Java 具有完整的面向对象特性。
- 封装:通过访问修饰符(如private、public、protected)可以控制类的成员变量和方法的访问权限,实现数据的封装。例如,一个BankAccount类可以将账户余额设为private,通过公共的方法(如deposit和withdraw)来操作余额,从而保证数据的安全性和完整性。
- 继承:可以创建子类继承父类的属性和方法。例如,SavingsAccount类可以继承BankAccount类,并且可以添加自己特有的属性和方法,如利息计算方法。这使得代码复用变得更加容易,同时也符合现实世界中的层次关系。
- 多态:Java 支持方法重写和接口实现等多态机制。例如,有一个Shape接口,Circle和Rectangle类都实现了这个接口,并且重写了calculateArea方法。在处理Shape类型的对象集合时,可以统一调用calculateArea方法,根据对象的实际类型(Circle或Rectangle)来执行不同的计算,这体现了多态性,使得代码更加灵活和可扩展。
虽然 C 语言主要是面向过程编程,Java 主要是面向对象编程,但这并不意味着 C 语言不能实现面向对象的一些概念,也不意味着 Java 不能有面向过程的部分代码。只是它们在设计理念和主要编程范式上有所不同,以适应不同的编程需求和场景。
总结
总之,Java 的面向对象编程为我们提供了一种强大的编程范式。通过类和对象、封装、继承和多态这些核心概念,我们可以构建出结构清晰、易于维护和扩展的软件系统。无论是小型项目还是大型企业级应用,掌握 Java 面向对象编程都是迈向成功的关键一步。希望这篇博客能帮助大家更好地理解和应用 Java 面向对象编程的知识。