面向对象与面向过程
在学习过程中,会遇到有别人的话里夹杂着面向对象啊之类的,就很懵,什么是面向对象?然后发现C语言是面向过程的,什么是面向过程的?
任何事物都要给自己一个动力、兴趣、坚持、希望,没有人是永恒的,只有内心自我的愿意也好、愿景也好、爱也好、天马行空什么都行所带来的一份热烈是永恒的。但是也有前提,为什么学习能坚持,因为学习给我的回应是知识面提升、思想的完善,一份工作、一种自信、一把未来的钥匙。所以有时候说念念不忘,必有回响,我觉得应该加一句相辅相成,那就是因有回响,念念不断。
百度百科解释这两种思想:
面向过程(c语言):就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用
面向对象(c++,c#,java,delphi):是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为
我的通俗而概要的理解:
面向过程(c语言):注重“如何”这个词,是一个个方法,是把所有过程捋清楚,像是一件事的流程+方法
-
特性:模块化 流程化
-
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开 发,性能是最重要的因素。
-
缺点:没有面向对象易维护、易复用、易扩展
面向对象(c++,c#,java,delphi):像是一句话的主语,用对象分解事情,事情本身不变,但是执行的对象不同。所以是给予对象属性,对象之下的“如何”这个方法是封装的,对象调用,是这么一个行为。
-
特性:抽象 封装 继承 多态
-
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
-
缺点:性能比面向过程低
其实我还是很晕的,而且上面这只是我现在的理解,2021.4.4 。
2021年6月4日更新
- 每个对象具有三个特点:对象的状态,对象的行为和对象的标识。
- 对象的状态用来描述对象的基本特征。
- 对象的行为用来描述对象的功能。
- 对象的标识是指对象在内存中都有一个唯一的地址值用来和其他对象区分开来。
- 类是一类事物的抽象,对象是具体的实现。
简单概述:对象是具体的,类是抽象的。从常规认知来看,类是将对象的属性,功能这些通性抽取出来归为不同类别,是抽象出来的。而从面向对象的编程来看,是先有类,后有对象。类通过成员变量描述属性,通过方法描述功能/行为,从而形成一个“模板”,然后new对象调用类里的这些属性和方法。
面向对象是注重结果,面向过程是注重过程。面向过程是一件事情的具体解决流程,如洗衣服是拿出脏衣服,打开洗衣机,倒入洗衣液·····等具体的流程。而面向对象是分配个对象去执行,至于怎么执行,做了哪些,并不重要,我们的目标是洗干净就行,比如你分配张三去洗衣服,洗好了给你就行。面向过程,你是详细的执行者。面向对象,你是分配者。
测试面向对象
package cn.jhf.test;
//用来测试面向对象
public class Test004 {
public static void main(String[] args) {
//new一个对象
Student j = new Student();
j.name = "jhf";
j.eat();
j.chooseSubject();
j.setAge(18);
j.getAge();
System.out.println(j.name);
System.out.println(j.getAge());
}
}
//用class创建一个类
class Student{
//成员变量描述属性
//没有赋值,为默认初始化值
String name;
char sex;
int schoolNum;
//封装age这个变量
private int age;
//给age提供公共的属性设置方式
public void setAge(int a) {
age = a;
}
//提供公共的属性查看方式
public int getAge() {
return age;
}
public void eat() {
System.out.println("吃食堂");
}
private void study() {
System.out.println("语数英政史地物理化生");
}
public void chooseSubject() {
study();
}
}
测试面向对象的封装,方法调用,成员变量的封装,构造方法
package cn.jhf.test;
//测试面向对象OOP,封装,对象,类,构造方法
public class Test005 {
public static void main(String[] args) {
//new 一个对象
Phone p1 = new Phone();//new对象时,同时执行了构造代码块与构造方法以及里面的局部代码块,构造代码块优先于构造方法。构造方法根据参数列表确定执行哪一个
System.out.println(p1.color);//没有给color赋值,所以是对应类型的默认值
p1.size = 10.5;//给p1对象的size赋值
System.out.println(p1.size);
p1.setPrice(1999);//利用公共的属性设置方法给price设置值
System.out.println(p1.getPrice());//利用公共的属性查看方法查看price的值
Phone p2 = new Phone("哈哈");
p2.color = "绿色";
System.out.println(p2.color);
/*没有给p2的size赋值,所以是对应类型的默认值。
*如果在Phone的类里给成员变量size加静态修饰static,则可以调用p1对象的赋值
*/
System.out.println(p2.size);
p2.setPrice(4999);
System.out.println(p2.getPrice());
Phone p3 = new Phone(666,"哈哈");
//调用行为/功能,
p3.num();
p3.call();
p3.net();
System.out.println(p3.music);
}
}
class Phone{
//成员变量
String color;
double size;
String music;
//构造代码块
{
music = "晴天";
System.out.println("检测构造代码块是否优先执行了");
}
//封装成员变量price
private int price;
//提供公共的属性设置方式
public void setPrice(int a) {
price = a;
}
//提供公共的属性查看方式
public int getPrice() {
return price;
}
//构造方法,构造方法的方法名和类名一致,且没有返回值类型
//构造方法在new对象时,如Phone p = new Phone();时,就同时调用的第一个无参构造方法
//如Phone p = new Phone("哈哈");时,就同时调用第二个构造方法
//由此可见,调用哪个构造方法,是根据方法里参数列表确定的
//所以构造方法可以方法的重载。满足同一个类里,多个方法名一样,参数列表不同。
public Phone() {
System.out.println("我是Phone的无参构造方法,new对象的时候直接同时运行"+music);
//创建一个局部代码块
{int i = 5;
System.out.println(i+"检测局部代码块运行顺序");
}
}
public Phone(String a) {
String music = "夜的第七章";
//这里局部变量music和成员变量music重名了,正常是就近原则,但是可以使用this.music取得成员变量的值
System.out.println("我是Phone的"+a+"构造方法,new对象的时候直接同时运行"+this.music);
}
public Phone(int a ,String b) {
this("七里香");//通过this(对应类型)获得Phone(String a)的能力,而且this关键字必须在 构造方法 的首行
System.out.println("我是Phone的"+a+"构造方法,new对象的时候直接同时运行"+b+music);
}
//创造方法描述行为/功能
public void call() {
System.out.println("打电话");
this.net();//通过this获得net()方法的功能,可以不在普通方法的第一行
}
public void net() {
//this.call() 这里必须注释掉,因为不能同时互相调用
System.out.println("百度一下");
}
private long phoneNumber(long a) {
return a;
}
public void num() {
System.out.println(phoneNumber(12345678910L));
}
}
结果:
- 成员变量可以封装,封装后可以用 setAbc 设置,可以用 getAbc 查看
比如上面代码里的:
private int price;
public void setPrice(int a) {
price = a;
}
public int getPrice() {
return price;
那么在对象调用时:
对象 . setPrice(对应变量类型)
System.out.print(对象.getPrice())
-
用来描述功能的方法也可以封装,想调用封装的方法,可以在公共的方法里引用封装私有的方法,然后对象调用此公共的方法。
-
在上面的案例里可以看出,构造方法全都没有返回值类型。直接就是 修饰符 方法名(参数列表){ };
-
构造方法的方法名都一样,并且就是类名。
-
构造方法的参数列表不同(参数的个数或者对应位置的参数类型不同),所以构造方法也可以重载。
-
无参构造方法默认伴随对象的生成而同时生成,如果要修改参数等可以写出来后进行修改