你想过吗,为什么说面向对象最符合人的思维?

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

在学习Java的过程中,我觉得面向对象是我遇到的第二个难题(第一个就是配置环境变量,哈哈)。我相信也有很多同胞也在这里被绊脚了吧,今天的话也就是其实也只是作为笔记写的这篇博客。

一、面向对象

这里也就不讲的太官方了,简单来说,我们编程都是基于对象的。就是我们做数学计算需要用Math类,我们画图需要Graphic类,我们操作文件需要File类。。。要具体解释什么是基于对象,那就要像讲两个概念。

1、类

类的话,通俗来说就是菜谱、模具之类的东西。我们可以根据菜单做出菜,可以根据模具做出相应的东西。类就和它们类似,通过类我们可以做出相应的实体,也就是对象。

2、对象

在学习面向对象时,经常会遇到“万物皆对象”这句话。其实这就已经解释了啥是对象。像普通的现实生活中,一个人,一条狗,一只猪,这种对象比较好理解。再抽象一点,一个多用的螺丝刀也是一个对象。而里面每个工具都是它的属性(Field)或者方法(Method)。

类别Java代码的话,人就是通过Person类new出来的一个对象。多用螺丝刀就是一个工具类,每种螺丝刀就是一只方法。下面举个例子,先写一个人的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
arduino复制代码/**
* 人类
*/
public class Person(){

String name;

int age;

String sex;

/**
* 构造方法
*/
public Person(){

}
}

这个时候我们可以通过构造方法,创建人的对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ini复制代码public class Test{

public static void main(String[] args){

//创建名为zack的Person类对象
Person zack = new Person();

//设置zack的属性
zack.name = "zack";
zack.age = 20;
zack.sex = "male";

}

}

接下来写个工具类,多用螺丝刀:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
csharp复制代码public class Tools{

/*十字螺丝刀*/
public void toolForTen(){
System.out.println("我是一把十字螺丝刀");
}


/*一字螺丝刀*/
public void toolForOne(){
System.out.println("我是一把一字螺丝刀");
}

/*手机螺丝刀*/
public void toolForPhone(){
System.out.println("我是一把手机螺丝刀");
}

}

然后我们来使用这个工具箱:

1
2
3
4
5
6
7
8
9
10
11
12
typescript复制代码public static void main(String[] args){

//先创建(制造)一个多用螺丝刀
Tool tool = new Tool();

//用螺丝刀开手机
tool.toolForPhone();

//用螺丝刀开十字螺丝
tool.toolForTen();

}

关于面向对象的概念就先说这么多,然后说说面向对象的三大特性。

二、封装

1、封装思想

这里的话,也不讲多复杂。有两个计较贴切的词语“隐藏细节”、“数据安全”。直白的说,就是有所保留。我们前面写的Person类,对于女性来说年龄是比较敏感的。但是我们只要把这个女性创建出来,就可以自己访问或者设置她的年龄,这样就非常的不安全,没有隐私可言。这个时候就需要用到封装思想。

2、封装的实现

主要的话就是给属性和方法设置访问权限,一般的话就是把全部属性(变量)设置为private,然后创建get、set方法。按照实际情况或者程序员的期望给方法设置不同权限。下面举个例子:

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
arduino复制代码/**
* 人类,利用封装思想改进代码
*
* 在这个类中sex为私有变量,且为提供相应的方法获取,故外部不能直接获取Person的性别
*/
public class Person{

private String name;

private int age;

private String sex;

/**
* 允许其他人知道我的名字,故设置为public(公共的)
*/
public String getName(){
return name;
}

public void setName(String name){
this.name = name;
}

}

修改之后性别就成了隐私了(当然了,在反射面前还是不值一提)。不过这些修饰词只在编译期起作用,所以这些属性其实还是可以通过反射获取。

这边的再扩展一下其它权限修饰词,就一张图,我盗来的:

三、继承

1、父类/基类

我在一篇文章中看到:不是先有父类(基类)再有子类,而是在不同类中发现许多共同点,然后把这些共同点抽出一个父类。先不说对错,我觉得这句话很好的解释了父类的意义。通俗来说的话,父类就是一个类,被继承的类。

2、子类

子类就是继承别人的类。

上面的解释好像毫无意义,但是把父类子类拆开讲本身就是毫无意义的。

3、继承的含义及性质

3.1、继承的话以来与关键词extends(延伸),就如它的意思,延伸、扩展。可以理解为,子类是父类的延伸


3.2、继承的话只能继承父类的非私有变量和方法


3.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
csharp复制代码/**
* 猫科动物的类
*/
public class Felidae{

protected String name;

protected int age;

//省略get、set方法

public void run(){
System.out.println(name + "在跑步");
}

public void eat(){
System.out.println(name + "在吃东西");
}

/**
* 无参构造
*/
public Felidae(){

}

/**
* 带参构造
*/
public Felidae(String name){
this.name = name;
}

}

然后定义一个老虎类继承猫科动物类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
scala复制代码/**
* 老虎类,继承猫科动物
*
* 在编写老虎类时,不需要考虑猫科动物的共性(年龄/名称)。
*
*/
public class Tiger extends Felidae{
//不是所有猫科动物都有花纹,其它什么特点我也想不到了就不纠结了
private String pattern;

//老虎会游泳
public void swim(){
System.out.println("老虎在游泳");
}

}

因为想象力匮乏,就这样简单介绍一下。这个继承了猫科动物的老虎没有定义name和age,但实际上我是可以使用这两个变量的:

1
2
3
4
5
6
7
8
9
java复制代码@Test
public void demo1(){
Tiger tiger = new Tiger();

//Tiger中没有setName()方法,但是Tiger继承了Felidae
//中的get/set方法(当然了,我在写类的时候省略了)
tiger.setName("rudy");
tiger.setAge(4);
}

四、多态

1、多态的关键在于继承、方法重写、方法重载

2、方法重写:在子类中创建一个与父类中同名,参数相同的方法。如下:

先写个Animal类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
csharp复制代码/**
* 动物类
*/
public class Animal{

protected String name;

protected String sex;

protected int age;

public void eat(){
System.out.println("动物会吃饭");
}

public void walk(){
System.out.println("动物会走路");
}

public void sleep(){
System.out.println("动物会睡觉");
}

}

然后定义一个Cat类,继承Animal,这里只重写一个方法用来举例:

1
2
3
4
5
6
7
scala复制代码public class Cat extends Animal{

public void eat(){
System.out.println("猫会吃东西");
}

}

这个时候调用Cat的eat方法的结果就是:

1
复制代码猫会吃东西

而父类中的eat方法被覆盖重写了。

3、方法重载,就是在同一个类中,方法名相同,但是传入参数不同,前面我们已经用到了方法重载。就是构造方法,有无参构造和有参构造,这就是一种方法重载,下面再给大家举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typescript复制代码public class Cat extends Animal{

public void eat(){
System.out.println("猫会吃东西");
}

public void eat(String name){
System.out.println(name + "猫会吃东西");
}

public void eat(String name, String food){
System.out.println(name + "会吃" + food);
}

}

上面三个方法同名,但是参数不同,在使用的时候可以通过传入参数自动识别是哪个方法,所以就实现了方法重载的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码@Test
public void demo1(){
Cat cat = new Cat();

//输出结果为:猫会吃东西
cat.eat();

//输出结果为:Tom会吃东西
cat.eat("Tom");

//输出结果为:Tom会吃Jerry
cat.eat("Tom", "Jerry");
}

4、多态三个必要条件继承、方法重写、父类引用指向子类:

1
2
3
4
5
6
7
8
9
java复制代码@Test
public void demo1(){
//前面创建Cat的方式可以修改为,这就是父类的引用指向子类
Animal cat = new Cat();

//在Cat中重写了Animal的eat()方法
cat.eat();

}

那么这段代码输出结果是:

1
复制代码猫会吃东西

因为是通过Cat类new出来的,而Cat中有一个eat方法,把Animal中的eat方法重写了。所以最后的结果是“猫会吃东西”。

面向对象中还有很多奇妙的东西,需要你们自己慢慢探索。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%