面向对象
1、面向过程和面向对象有什么区别?
从语言方面出发:
对于C语言来说,是完全面向过程的。
对于C++语言来说,是一半面向过程,一半是面向对象。(C++是半面向对象的)
对于Java语言来说,是完全面向对象的。
什么是面向过程的开发方式?
面向过程的开发方式主要的特点是:
注重步骤,注重的是实现这个功能的步骤。
第一步干什么
第二步干什么
....
另外面向过程也注重实现功能的因果关系。
因为A所有B
因为B所以C
因为C所以D
.....
面向过程中没有对象的概念。只是实现这个功能的步骤以及因果关系。
面向过程有什么缺点?(耦合度高,扩展力差。)
面向过程最主要是每一步与每一步的因果关系,其中A步骤因果关系到B
步骤,A和B联合起来形成一个子模块,子模块和子模块之间又因为因果
关系结合在一起,假设其中任何一个因果关系出现问题(错误),此时
整个系统的运转都会出现问题。(代码和代码之间的耦合度太高,扩展力
太差。)
螺栓螺母拧在一起:耦合度高吗?
这是耦合度低的,因为螺栓螺母可以再拧开。(它们之间是有接口的。)
螺栓螺母拧在一起之后,再用焊条焊接在一起,耦合度高吗?
这个耦合度就很高了。耦合度就是黏连程度。
往往耦合度高的扩展力就差。
耦合度高导致扩展力差。(集成显卡:计算机显卡不是独立的,是集成到主板上的)
耦合度低导致扩展力强。(灯泡和灯口关系,螺栓螺母关系)
采用面向过程的方式开发一台计算机会是怎样?
这台计算机将没有任何一个部件,所有的都是融合在一起的。
你的这台计算机是一个实心儿的,没有部件的。一体机。
假设这台一体机的任何一个“部位”出问题,整个计算机就不能用了,
必须扔掉了。(没有对象的概念。)
采用面向对象的方式开发一台计算机会是怎样?
内存条是一个对象
主板是一个对象
CPU是一个对象
硬盘是一个对象
然后这些对象组装在一起,形成一台计算机。
假设其中CPU坏了,我们可以将CPU拆下来,换一个新的。
面向过程有什么优点?(快速开发)
对于小型项目(功能),采用面向过程的方式进行开发,效率较高。
不需要前期进行对象的提取,模型的建立,采用面向过程
方式可以直接开始干活。一上来直接写代码,编写因果关系。
从而实现功能。
什么是面向对象的开发方式?
采用面向对象的方式进行开发,更符合人类的思维方式。(面向对象成为主流的原因)
人类就是以“对象”的方式去认识世界的。
所以面向对象更容易让我们接受。
面向对象就是将现实世界分割成不同的单元,然后每一个单元
都实现成对象,然后给一个环境驱动一下,让各个对象之间协
作起来形成一个系统。
对象“张三”
对象“香烟”
对象“打火机”
对象“吸烟的场所”
然后将以上的4个对象组合在一起,就可以模拟一个人的抽烟场景。
其中“张三”对象可以更换为“李四”
其中“香烟”也可以更换品牌。
其中“打火机”也可以更换。
其中“吸烟的场所”也可以更换。
采用面向对象的方式进行开发:
耦合度低,扩展力强。
找一个合适的案例。说明一下面向对象和面向过程的区别?
蛋炒饭:
鸡蛋和米饭完全混合在一起。没有独立对象的概念。
假设客户提出新需求:我只想吃蛋炒饭中的米饭,怎么办?
客户提出需求,软件开发者必须满足这个需求,于是
开始扩展,这个软件的扩展是一场噩梦。(很难扩展,耦合度太高了。)
盖饭:
老板,来一份:鱼香肉丝盖饭
鱼香肉丝是一道菜,可以看成一个独立的对象。
米饭可以看成一个独立的对象。
两个对象准备好之后,只要有一个动作,叫做:“盖”
这样两个对象就组合在一起了。
假设客户提出新需求:我不想吃鱼香肉丝盖饭,想吃西红柿鸡蛋盖饭。
这个扩展就很轻松了。直接把“鱼香肉丝”对象换成“西红柿鸡蛋”对象。
当我们采用面向对象的方式贯穿整个系统的话,涉及到三个术语:
OOA:面向对象分析
OOD:面向对象设计
OOP:面向对象编程
整个软件开发的过程,都是采用OO进行贯穿的。
实现一个软件的过程:
分析(A) --> 设计(D) --> 编程(P)
在软件公司当中,一般同事与同事之间聊天,有的时候会突然说出来一个英语单词。
这种情况是很常见的。所以一些术语还是要知道的,不然会闹出笑话。
leader 领导/经理/组长
team 团队
PM 项目经理(整个项目的监管人)Project Manager
2、类和对象的概念
面向对象当中最主要“一词”是:对象。
什么是类?
类实际上在现实世界当中是不存在的,是一个抽象的概念。
是一个模板。是我们人类大脑进行“思考、总结、抽象”的一个
结果。(主要是因为人类的大脑不一般才有了类的概念。)
类本质上是现实世界当中某些事物具有共同特征,将这些共同
特征提取出来形成的概念就是一个“类”,“类”就是一个模板。
明星是一个类
什么是对象?
对象是实际存在的个体。(真实存在的个体)
宋小宝就是一个对象
姚明就是一个对象
刘德华就是一个对象
....
宋小宝、姚明、刘德华这3个对象都属于“明星”这个类。
在java语言中,要想得到“对象”,必须先定义“类”,“对象”是通过“类”
这个模板创造出来的。
类就是一个模板:类中描述的是所有对象的“共同特征信息”
对象就是通过类创建出的个体。
这几个术语你需要自己能够阐述出来:
类:不存在的,人类大脑思考总结一个模板(这个模板当中描述了共同特征。)
对象:实际存在的个体。
实例:对象还有另一个名字叫做实例。
实例化:通过类这个模板创建对象的过程,叫做:实例化。
抽象:多个对象具有共同特征,进行思考总结抽取共同特征的过程。
类 --【实例化】--> 对象(实例)
对象 --【抽象】--> 类
类是一个模板,是描述共同特征的一个模板,那么共同特征包括什么呢?
潘长江对象:
名字:潘长江
身高:165cm
打篮球:非专业的,自己玩儿呢,无所谓了
学习:考试80分
姚明对象:
名字:姚明
身高:240cm
打篮球:NBA专业球员,打篮球非常棒
学习:考试100分
共同特征包括哪些?
名字、身高都属于名词(状态特征)
打篮球、学习都属于动词(动作特征)
类 = 属性 + 方法
属性来源于:状态
方法来源于:动作
public class 明星类{
//属性-->状态,多见于名词
名字属性;
身高属性;
//方法-->动作,多见于动词
打篮球方法(){
}
学习方法(){
}
}
陈赓同学、何伟彬同学,他们俩有没有共同特征呢?
有共同特征,就可以抽象一个类模板出来。
可以定义一个学生类(Student)
public class Student {
// 属性
// 姓名
// 性别
// 身高
// 方法
public .... sing(){
}
public .... dance(){
}
public .... study(){
}
....
}
2.1类的定义
[修饰符列表] class 类名 {
//类体 = 属性 + 方法
// 属性在代码上以“变量”的形式存在(描述状态)
// 方法描述动作/行为
}
注意:修饰符列表可以省略。
为什么属性是“以”变量的形式存在的?
答案:是因为属性对应的是“数据”,数据在程序中只能放到变量中。
结论:属性其实就是变量。
变量的分类
变量根据出现位置进行划分:
方法体当中声明的变量:局部变量。
方法体外声明的变量:成员变量。(这里的成员变量就是“属性”)
2.2对象创建和使用
类(java中定义的和我们自己定义的)是一个引用类型,使用有固定的三个步骤:
1.导包(找到我们要使用的东西)
格式: import 包名.类名;
注意:
(1)java.lang包下的内容,不需要导包可以直接使用
(2)如果当前类和要使用的类在同一个保重,也不需要导包
导包快捷键: alt + 回车
2.创建对象:
数组的创建:
数据类型[] 数组名称 = new 数据类型[长度];
举例:
Scanner sc = new Scanner(System.in);
Random r = new Random();
格式:
类名 对象名 = new 类名(参数...);
Student stu = new Student();
3.对象的使用:
(1)对象名称: 对象在堆内存空间的地址值
(2)成员变量的使用:
对象名称.成员变量名称
stu.name: 对象的name属性
(3)成员方法的使用:
对象名称.成员方法名称(参数列表...);
stu.eat(): 调用对象stu的eat方法
2.3成员变量和局部变量的区别
1.在类中的位置不同【重点】
成员变量:类中,方法外
局部变量:方法中或者方法声明上(形式参数)
2.作用范围不一样【重点】
成员变量:类中
局部变量:方法中
3.初始化值的不同【重点】
成员变量:有默认值
局部变量:没有默认值。必须先定义,赋值后再使用
4.在内存中的位置不同(了解)
成员变量:堆内存
局部变量:栈内存
5.生命周期不同(了解)
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
public class Person {
//成员变量
String name;//在该类的所有的成员方法内部都可以使用
//成员方法
/*
下面是在定义方法show,内部使用的局部变量s和num,
要保证在方法运行时必须有值才可以
*/
public void show(String s) {//在方法定义时()中指定的变量: 形式参数,也叫作局部变量
//方法内部定义变量:局部变量,只在show方法内部有效
int num ;
System.out.println(name);
System.out.println(s);//hello
//局部变量num,没有默认值: 不赋值不能使用的
//num = 1000;
//System.out.println(num);
}
public void method() {
//错误: num和s是局部变量,只能在show方法内部使用
//num = 10;
//s = "hello";
System.out.println(name);
}
}
public class Demo01Person {
public static void main(String[] args) {
//创建Person类的对象
Person p = new Person();
System.out.println(p.name);//默认值: null
//调用成员方法
p.show("hello");
}
}
2.4对象和引用的区别
对象是通过new出来的,在堆内存中存储。
引用是:但凡是变量,并且该变量中保存了内存地址指向了堆内存当中的对象的。
2.5类与对象
/*
定义手机Phone类,用来模拟现实中的手机事物
成员变量:和以前定义变量相同,位置不同,在类中方法外
品牌: String brand
颜色: String color
价格: int price
成员方法:和以前定义方法格式相同,去掉static关键字
打电话: void call(String who)
发短信: void sendMessage(String who,String msg)
*/
/*
这里定义了一个名称为Phone的类,用来描述手机事物,相当于模板/模型/图纸,
不能直接使用,要想使用,必须根据模板/模型/图纸创建(如何创建一个具体的对象呢?)一个具体的手机对象才可以使用.
抽象:
抽取出现实事物中像的部分,相同的部分,相似的部分
*/
public class Phone {
//成员变量
String brand;//品牌
String color;//颜色
int price;//价格
//成员方法
//打电话
public void call(String who) {
System.out.println("正在给..."+who+"...打电话...");
}
//发短信
public void sendMessage(String who, String msg) {
System.out.println("正在给..."+who+"...发短息: "+msg);
}
}
3.理解练习
动物之猫和狗练习
需求:
猫类Cat
属性:
color:毛的颜色
breed:品种
行为:
eat():吃饭
catchMouse():抓老鼠
狗类Dog
属性:
color:毛的颜色
breed:品种
行为:
eat():吃饭
lookHome():看家
要求:
1.按照以上要求定义Cat类和Dog类
2.定义测试类,在main方法中创建该类的对象并给属性赋值
3.调用成员方法,打印格式如下:
花色的波斯猫正在吃鱼.....
花色的波斯猫正在逮老鼠....
黑色的藏獒正在啃骨头.....
黑色的藏獒正在看家.....
public class Cat {
//成员变量
String color;//毛的颜色
String breed;//品种
//成员方法
//吃饭
public void eat() {
System.out.println(color+"的"+breed+"正在吃鱼.....");
}
//抓老鼠
public void catchMouse() {
System.out.println(color+"的"+breed+"正在逮老鼠....");
}
}
public class Dog {
//成员变量
String color;//毛的颜色
String breed;//品种
//成员方法
//吃饭
public void eat() {
System.out.println(color+"的"+breed+"正在啃骨头.....");
}
//看家
public void lookHome() {
System.out.println(color+"的"+breed+"正在看家.....");
}
}
public class Demo01CatAndDog {
public static void main(String[] args) {
//创建Cat类的对象
Cat cat = new Cat();
//给成员变量赋值
cat.color = "花色";
cat.breed = "波斯猫";
//调用成员方法
/*
使用cat对象调用eat和catchMouse方法时,
这两个方法内部使用的变量color和breed,
是cat对象内部的color和breed
*/
cat.eat();
cat.catchMouse();
System.out.println("-------------");
//创建Dog类的对象
Dog dog = new Dog();
//给成员变量赋值
dog.color = "黑色";
dog.breed = "藏獒";
//调用成员方法
/*
使用dog对象调用eat和lookHome方法时,
这两个方法内部使用的变量color和breed,
是dog对象内部的color和breed
*/
dog.eat();
dog.lookHome();
}
}
4.private关键字
发现问题:
定义类时,虽然指定了成员变量的含义(比如:age代表年龄),
但是却无法保证成员变量的取值在一个合理有效的范围之内
比如:
年龄age: 必须在[0,100]之间 age>=0 && age<=100
解决方案: private关键字,private单词: 私有
1.private关键字的使用:
将需要保护的成员变量使用private关键字,修饰一把
2.使用格式:
(1)修饰成员变量: private 数据类型 变量名称;
(2)修饰成员方法: private 返回值类型 方法名称(参数列表...){...}
3.可以修饰的内容:
(1)成员变量
(2)成员方法
(3)构造方法【以后讲】
(4)内部类【以后讲】
4.被private修饰的成员的访问特点:
(1)被private修饰的成员(成员变量/成员方法),可以在本类(定义成员所在的类)中使用
(2)被private修饰的成员(成员变量/成员方法),不能在其它类中直接使用(对象名.成员变量名)
5.private修饰成员后暴露新的问题:
被private修饰的成员(成员变量/成员方法),不能在其它类中直接使用(对象名.成员变量名)
但是可以在其它类中通过set方法/get方法间接访问被private修饰的成员变量
(1)为被private修饰的成员变量提供set方法: 作用是修改成员变量的值
三要素:
a.方法名称: set+成员变量名称(第一个字母大写)
b.参数列表: 定义一个和成员变量类型相同的参数
c.返回值类型: void
发现提供set方法后,仍然可以给成员变量随便赋值:
解决方案: 可以在方法内部添加逻辑判断,限制成员变量的取值
(2)为被private修饰的成员变量提供get方法:作用是获取成员变量的值
三要素:
a.方法名称: get+成员变量名称(第一个字母大写)
b.参数列表: 不需要
c.返回值类型: 需要获取值的成员变量的类型
public class Person02 {
//成员变量
String name;//姓名
private int age;//年龄
/*
定义给成员变量age赋值的set方法: setAge
*/
public void setAge(int a) {
if (a >= 0 && a <= 100) {
age = a;
}
}
/*
定义获取员变量age值的get方法: getAge
*/
public int getAge() {
return age;
}
//成员方法
//展示信息的方法
public void show() {
System.out.println("姓名: "+name+", 年龄: "+age);
}
}
public class Demo02Problem {
public static void main(String[] args) {
//创建Person01类的对象
Person02 p = new Person02();
//给成员变量赋值
p.name = "灭绝师太";
//错误: age被private修饰,其它类中不能直接使用(对象名.成员变量名)
//p.age = 18;
//调用成员方法setAge给成员变量age赋值
p.setAge(18);
//调用成员方法
p.show();
//给age重新赋值
//错误: age被private修饰,其它类中不能直接使用(对象名.成员变量名)
//p.age = 8848;
//调用成员方法setAge给成员变量age赋值
p.setAge(8848);
//调用成员方法
p.show();
//给age重新赋值
//错误: age被private修饰,其它类中不能直接使用(对象名.成员变量名)
//p.age = -9999;
//调用成员方法setAge给成员变量age赋值
p.setAge(-9999);
//调用成员方法
p.show();
//调用getAge方法,获取成员变量age的值
int age = p.getAge();
System.out.println("年龄是: "+age);
}
}
5.static关键字
static修饰的统一都是静态的,都是类相关的,不需要new对象。直接采用“类名.”访问。
当一个属性是类级别的属性,所有对象的这个属性的值是一样的,建议定义为静态变量。
6.this关键字
this代表当前对象,谁调用就代表谁
访问规则:
就近原则: 方法内部有,直接使用,方法内部没有,找成员变量
this关键字的作用
用来区分局部变量和成员变量同名的情况的
应用:
/*
到目前为止,定义标准的Java类的要求:
1.所有成员变量private修饰
2.为每个成员变量通过set方法(修改成员变量的值)和get方法(获取成员变量的值)
注意:
set/get方法快捷键:
alt + insert --> Getter and Setter --> 选定成员变量 --> ok
右键/generate --> Getter and Setter --> 选定成员变量 --> ok
*/
public class Person04 {
//成员变量
private String name;//姓名
private int age;//年龄
//成员方法
public void show() {
System.out.println("姓名: "+name+", 年龄: "+age);
}
//setName方法: 给成员变量name赋值
public void setName(String name) {
this.name = name;
}
//getName方法:获取成员变量name的值
public String getName() {
return name;
}
//setAge方法: 给成员变量age赋值
public void setAge(int age) {
this.age = age;
}
//getAge方法: 获取成员变量age的值
public int getAge() {
return age;
}
}
public class Demo04UsePrivateThis {
public static void main(String[] args) {
//创建Person04类的对象
Person04 p = new Person04();
//调用set方法给成员变量赋值
p.setName("张三");
p.setAge(18);
//调用成员方法show,展示信息
p.show();
//调用get方法获取成员变量的值
String n = p.getName();
int a = p.getAge();
System.out.println("姓名: "+n+", 年龄: "+a);
}
}
7.构造方法
7.1构造方法的介绍
创建对象的格式:
类名 对象名 = new 类名();
举例:
Person05 p = new Person05();
创建对象的过程(死的java规定的过程): new关键字 + 调用构造方法
构造方法:
1.作用:
当使用new关键字创建对象后(对象中成员变量都是默认值),
必须要通过调用构造方法完成对象成员变量的初始化赋值
2.格式:
修饰符 构造方法名称(参数列表...) {
方法体;
return ;
}
3.特点:
(1)修饰符中没有static关键字
(2)没有返回值类型,连void都不能写
(3)构造方法名称必须和类名称保持一模一样
(4)参数列表根据需求确定
(5)return后面不能跟具体的数据值,只能写return ;
建议可以省略
4.注意:
(1)自己定义类时,如果没有自己定义任何构造方法,编译器会隐藏提供一个空参构造方法(没有参数)
(2)自己定义类时,如果自己定义了任何一个构造方法,编译器不会在隐藏提供一个空参构造方法(没有参数)
(3)构造方法也是方法,既然是方法,就可以重载
7.2构造方法的使用
public class Person05 {
//成员变量
private String name;//姓名
private int age;//年龄
//空参构造方法
public Person05() {
System.out.println("空参构造方法被调用了....");
}
//满参构造方法
public Person05(String name, int age) {
this.name = name;
this.age = age;
}
//给name赋值的构造方法: 不常用
public Person05(String name) {
this.name = name;
}
//给age赋值的构造方法: 不常用
public Person05(int age) {
this.age = age;
}
//成员方法
public void show() {
System.out.println("姓名: "+name+", 年龄: "+age);
}
//setName方法: 给成员变量name赋值
public void setName(String name) {
this.name = name;
}
//getName方法:获取成员变量name的值
public String getName() {
return name;
}
//setAge方法: 给成员变量age赋值
public void setAge(int age) {
this.age = age;
}
//getAge方法: 获取成员变量age的值
public int getAge() {
return age;
}
}
public class Demo05Constructor {
public static void main(String[] args) {
//空参构造: 创建Person05类的对象
Person05 p = new Person05();
//调用set方法给成员变量赋值
p.setName("张三");
p.setAge(18);
//调用成员方法show展示信息
p.show();
System.out.println("---------------");
//满参构造: 创建Person05的对象
Person05 p2 = new Person05("李四", 28);
//调用成员方法show展示信息
p2.show();
}
}
8.代码块
语句块 | 位置不同 | 作用域 | 执行时间 |
---|---|---|---|
普通语句块{} | 方法内部 | 方法内部 | 调用方法时 |
构造块{} | 类内方法外 | 对象 | 创建对象时 |
静态块static{} | 类内 | 类 | 加载类时 |
注意:静态块,仅在类的第一次使用时加载。构造块,先于构造器执行,每创建一个对象执行一次