掌握Java面向对象OOP篇(一)
掌握面向对象OOP篇(一)
边学边记 -- OOP(Object Orientated Programing)
1. 为什么要引入面向对象?
原因:封装、继承、多态
举个例子理解面向对象代码的好处:
比如:我们有一个实际问题,假设现在一个宠物店有两只小狗, 第一只叫做小白,年龄2岁,白色;第二只叫做小红,年龄3岁,红色;现在我们的宠物店的系统可以让用户在输入不同狗的名字,能显示不同的狗的信息,如果没有,就输出该宠物店没有这条狗。
1.1 非面向对象
不使用面向对象:
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 面向对象:
使用面向对象
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.冗余和代码膨胀:随着狗的数量的增加 ,代码中的相似的定义和初始化操作变得冗余。这导致了代码的膨胀,使得程序变得庞大且难以维护。
//比如:我们需要反复的使用String dogName = "example";等等去定义属性。
2.可读性很差: 大量的重复代码使得程序的可读性变差。维护人员很难在代码中找到并理解与每只狗相关的所有信息。
//因为代码中有大量的对属性的定义,所以很难对应找到
3.难以修改:如果我们要对狗的属性进行修改、或者添加新的属性,那么整个代码的维护更新就会非常难以进行,并且容易出错。
//当代码量上来的时候,我们如果要给狗添加一个毛的长短的属性,那么我们就要添加几万行代码,很不合理。
4.缺乏结构性:独立变量或数组元素的方式缺乏结构,不易于组织和管理相关的信息。随着信息的增加,代码可能变得混乱且难以理解。
//代码看起来没有章法,不知道从哪里入手
使用面向对象的好处主要体现在以下几个方面:
1.封装和抽象: 面向对象编程强调封装,将对象的属性和行为封装在一起,提供了更高层次的抽象。这使得程序员可以专注于对象的接口,而不必关心内部的实现细节。这样的封装和抽象提高了代码的模块化和可维护性。
//比如我们的oobject3中的非主类部分,就是把属性和方法放在了(封装)类oobject3中,那么这个时候我们的主类去 new 出一个对象时,就可以直接使用这些属性和方法。因为这个方法和属性被封装成为了一个模板。我们通过这个模板new的狗子的这些属性和方法的使用都一样。那么这个模板就实现了很好的统一也降低了代码的重复量。这就是封装的好处。
2.可维护性和可扩展性: 面向对象的编程模型使得代码更易于维护和扩展。通过创建类和对象,可以轻松地添加新的功能或修改现有功能,而不必改变整个程序的结构。这种灵活性使得程序更具可维护性和可扩展性。
//当我们要添加属性时,我们只需要在oobject3中加一行代码,private String type; 那么所有的狗就可以用这个属性,不用去大量的改动代码。
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
" 这个引用来自狂神Java "
语言的进化发展跟生物的进化发展其实是一回事,都是”物以类聚”。
相近的感光细胞聚到一起变成了我 们的眼睛,相近的嗅觉细胞聚到一起变成了我们的鼻子。 语句多了,我们将完成同样功能的相近的语句,聚到了一块儿,便于我们使用。于是,方法出现了! 变量多了,我们将功能相近的变量组在一起,聚到一起归类,便于我们调用。于是,结构体出现了! 再后来,方法多了,变量多了!结构体不够用了!我们就将功能相近的变量和方法聚到了一起,于是类 和对象出现了! 寥寥数语,就深刻的展示了语言的进化历史!其实,都非常自然,”物以类聚”。希望大家能记住这句 话。 企业的发展也是”物以类聚”的过程,完成市场推广的人员聚到一起形成了市场部。完成技术开发的人员 聚到一起形成了开发部!
面向对象和面向过程的本质区别就是处理逻辑(思维模式)的不同。
1.面向过程的思维模式就是简单的线性思维,解决问题首先陷入第一步干什么、第二部干什么的细节中。这种思维模式适合处理一些简单的事务,别入从A走到B,把垃圾倒入垃圾桶等等。如果面对复杂的问题,那么解决就会很麻烦。
2.相反,面向对象更注重的是对问题的整体抽象和建模。它将问题中的实体抽象为一个个的对象,关注对象之间的交互。让对象去解决问题,这样的思维模式更加自然,更加贴近生活。
考虑一个复杂任务,比如设计并制造一艘航天飞船,面向过程的思维模式可能会让人感到困扰,因为这需要考虑众多细节和步骤。然而,通过面向对象的思维模式,我们可以将这个庞大的任务分解成对象,例如“引擎”、“控制系统”、“舱体”等,每个对象都有特定的属性和行为。这种抽象和分解使得我们能够更清晰地理解并解决问题,而不会被淹没在无尽的步骤中。
3.感受面向对象的美
我们直接使用代码去理解这个东西!!! 去感受为什么Java中的封装、继承、多态的好处
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 circle = new Circle("Red", 5.0);
System.out.println("Circle Area: " + circle.getArea());
System.out.println("Circle Color: " + circle.getColor());
// 创建 Rectangle 对象
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)
访问了父类的构造方法,这也是一种封装的体现,子类不需要直接访问父类的私有属性。
封装的好处:
封装提高了代码的安全性:将属性声明为私有,通过公有方法进行访问,防止外部直接修改对象的内部状态值,从而提高数据的安全性。
封装隐藏细节:封装允许隐藏内部实现细节,使得使用者只需要关注对象的公有接口。这样的设计可以降低了系统的复杂性,是代码更容易理解和维护。
封装提高灵活性:如果内部实现需要更改,只需保持公有接口不变,使用者不受影响。这种灵活性使得系统更容易适应变化。
在 Circle
和 Rectangel
类都是通过关键字extends继承自shape
抽象类。这使得子类获得了父类的属性和方法,实现了代码的重用。例如:两个类都继承父类的color属性和getColor方法。
继承的好处:
代码重用: 继承允许子类重用父类的代码,避免了重复编写相似的代码,降低了代码的重复率。
可维护性: 当需要修改或扩展功能时,只需在父类中进行修改,子类将自动继承这些变化。这降低了修改代码的风险,提高了可维护性。
多态支持: 继承是实现多态的基础。通过继承,不同的子类可以被视为同一类型的对象,提供了更灵活的代码结构。
在 shape
抽象类的抽象方法getArea中体现了多态。不同的子类分别重写了这个方法,根据自己的需求提供了具体的实现。在测试类中,通过统一的接口 getArea
调用,实际上调用了各个子类的实现,展现了多态性。
多态的好处:
灵活性和扩展性: 多态允许同一类型的对象以不同的方式响应相同的方法调用。这提高了代码的灵活性和可扩展性,使得系统更容易适应变化。
简化代码: 多态性允许使用者通过一个统一的接口调用不同类型的对象,简化了代码,提高了可读性。
实现抽象概念: 多态性使得我们能够以更抽象的方式思考和设计问题,将实际对象视为抽象概念的实例,有助于更清晰地理解和解决问题。
本文来自博客园,作者:柳~,转载请注明原文链接:https://www.cnblogs.com/zhiliu/p/17843787.html