面向对象思想----不看懊悔!
前言:
整理这份资料的目的是为了帮助朋友们可以更直观的理解面向对象的编程。让后来者可以少走一些弯路。但当中不免有很多漏洞及错误,也还
请前辈提出宝贵的更改意见,毕竟交流会让我们不断的进步。
技术是日新月异的,他不会等待你的成长。技术要拿出来于别人交流,自己学是自己主观意识上的理解,有对有错!交流会让进步变得更快。
我觉得假设计算机 的体系结构不发生革命性的变化,我们如今所应用的程序语言也就百变不离奇踪了!学编程学的是什么?思想!精通一门编
程语言(最好是面向对象的语言)后再去 搞其它的编程语言,你会发现过程是如此的行云流水!为什么?你已经把编程的思想掌握了,再去学
其它的,无非是学习一种新的语法格式了。
我在这里并非和你讨论怎么去用C++或JAVA,也不是和你讨论怎么去学他们,我要和你讨论的是怎么去理解面向对象。当中主要会涉及到“类
、对象、 继承、属性、方法、静态、重载、隐藏、重构、声明、定义、初始化、赋值等”当中有很多相关技术我仅仅会一代而过,让你有一种到
此一游的意味我就达到目的了, 而更具体的技术内幕,就请參考其它相关书籍而深入研究吧!由于我仅仅是在和你探讨怎样去更好的理解面向对
象!
怎样去提高效率?反复使用资源,把别人的东西拿来就用。这是非常不错的主意!而对于你来说,最大的资源就是信心以及积极性!好,打起精
神来,让我们一同到面向对象的编程中去寻幽訪胜吧!
注:文章中全部程序实例我都使用JAVA写的,当然在C++中也就大同小异了了,不同的地方我会指出!
注:文章中的正文文字用黑色,说明文字用蓝色,强调文字用橙色,批改文字用红色!
正文:
1.基本概念:
1.1 类与对象的初探
要我说,不管是面向过程的语言也好,面向对象的语言也罢,我首先要给他讲的都是类和对象!--------“这个世界是由什么组成的?”这个
问题假设 让不同的人来回答会得到不同的答案。假设是一个化学家,他或许会告诉你“还用问嘛?这个世界是由分子、原子、离子等等的化学
物质组成的”。假设是一个画家 呢?他或许会告诉你,“这个世界是由不同的颜色所组成的”。……呵呵,众说纷纭吧!但假设让一个分类学
家来考虑问题就有趣的多了,他会告诉你“这个世界是 由不同类型的物与事所构成的”好!作为面向对象的程序猿来说,我们要站在分类学家
的角度去考虑问题!是的,这个世界是由动物、植物等组成的。动物又分为单 细胞动物、多细胞动物、哺乳动物等等,哺乳动物又分为人、大
象、老虎……就这种分下去了!
如今,站在抽象的角度,我们给“类”下个定义吧!我的意思是,站在抽象的角度,你回答我“什么是人类?”首先让我们来看看人类所具有
的一些特征,这个 特征包含属性(一些參数,数值)以及方法(一些行为,他能干什么!)。每一个人都有身高、体重、年龄、血型等等一些属
性。人会劳动、人都会直立行走、人都会 用自己的头脑去创造工具等等这些方法!人之所以能差别于其他类型的动物,是由于每一个人都具有人
这个群体的属性与方法。“人类”不过一个抽象的概念,它只 是一个概念,它是不存在的实体!可是全部具备“人类”这个群体的属性与方
法的对象都叫人!这个对象“人”是实际存在的实体!每一个人都是人这个群体的一个对 象。老虎为什么不是人?由于它不具备人这个群体的属
性与方法,老虎不会直立行走,不会使用工具等等!所以说老虎不是人!
由此可见-------类描写叙述了一组有同样特性(属性)和同样行为(方法)的对象。在程序中,类实际上就是数据类型!比如:整数,小数等等。
整数也有 一组特性和行为。面向过程的语言与面相对象的语言的差别就在于,面向过程的语言不同意程序猿自定义数据类型,而仅仅能使用程
序中内置的数据类型!而为了模 拟真实世界,为了更好的解决这个问题,往往我们须要创建解决这个问题所必需的数据类型!面向对象编程为我们提供
了解决方式。
1.2 内置数据类型与函数:
计算机程序在存储数据时必须跟踪3个基本属性为:
1. 信息存储在何处;
2. 存储的值是多少;
3. 存储的信息是什么类型的;
让我们来看看编程语言的内置数据类型都有哪些!(呵呵,这个不大好说,由于每门语言都有自己独特的数据类型,但这毕竟是少数,比方在
JAVA中有 byte类型的数据,而在C++中就没有,希望你能举一反三!)比方整数”int ”,浮点类型的数据”float”!字符串”String”,以
及数组还有结构体等等。然而在敲代码的时候,依据须要我们会创建一个类型的变量或常量,例 如:因为我们须要创建一个整形的变量i为5,
我们就能够这样做,int i = 5;而依据须要我非常有可能改变i的值,也就是从新给它赋值,比方让它等与6,就能够在所需的地方改成i = 6;由
此我们知道,在“值”上能够发生变化的量就叫变量。不会发生变化的量就叫做常量了,在C++中用countkeyword来声明,而在JAVA中则使用
finalkeyword来声明。因为不同语言的声明格式不一样,这里就不做一一介绍了,具体的内容清查阅相关书籍!
在这里我们主要讨论一下函数,我们能够把函数想象成一个“实现某种特定功能的黑匣子”-------这个功能是由你来设定的,举个样例来说:
如今我问 你“2+3等于多少”?我相信你能非常快的回答我等于5。让我们来分析分析这句话包括什么信息!首先我要把你的大脑想象成是一个黑
匣子,我并不知道也没有必 要知道你的大脑是怎样工作的(也就是怎么运算的),我关心的仅仅是我传给你的是什么信息?你对信息做了哪些处
理? 以及你返回给我的是什么信息?须要提醒你一下的是每一个方法都会返回一个信息给调用者的,除了构造函数外(稍候我会作具体的介绍)
。我如今须要把自己当作是 一名程序猿,而你呢?当然就是计算机了!计算就可以没有人那么聪明,它仅仅会按事先约好的特定的格式执行,我想
让它具有如上所述的功能,我就要先定义这个黑匣 子!首先我要告诉这个黑匣子会有两个整数值给你(这就是所谓的參数,是程序猿须要给黑
匣子的信息),然后就要定义这个黑匣子内部实现这两个整数相加的运算 (这就是黑匣子对数据所做的加工,依据须要,你能够做不论什么的加工
。)。最后再标注它返回给我一个相同是整型的数值(这是黑匣子返回给程序猿的信息)。一个 函数就这样定义完了,让我们来看看书写格式
:
int addnum(int x,int y){
return x+y;
}
详细的含义是这种:
int /*返回值类型*/ addnum /*方法(黑匣子)名称*/ (int x,int y/*传入的參数*/){
return x+y; /*内部是想方法(实现相加运算,)并用return返回给调用者结果*/
}
首先请注意上明的“return”语句!return keyword的含义是向调用者返回紧跟在它后面的信息!就像上面一样,由于我问你,你才会回答我,
假设我不问你,你就不用回答我的!在计算机中也一样,定义好这 个函数在哪里调用呢?我仅仅能告诉你,哪里须要就在哪里调用!当然,你可
以依据须要去更改參数、返回值以及内部实现,详细到怎样定义怎样调用你仅仅好去參考相 关的资料了!在这里我仅仅是给你一个思想!
有时你会遇到这种问题,我让你记住,我的年龄是20岁!从字面上理解,你并没有给我返回信息!然而其实,你确实给我返回了信息,信
息的内容是“无信息,也就是无返回值类型void”。详细的程序例如以下:
int myAge = 0;
int a=20;
void remAge(int a){
myAge=a;
}
详细的函数说明例如以下:
int myAge =0; //定义并初始化我的年龄为0;
int a=20; /*定义变量a等于20*/
void /*返回值类型为无返回值类型*/ remAge /*函数名称*/(int a /*传入的參数*/){
myAge=a; //内部实现方法,注意,没有return返回!!!
}
关于函数的话题还有非常多非常多,这里就不一一介绍了,我的目的是让你知道函数是怎么一会事儿!为以下的讨论作铺垫!
1.3 指针以及引用:
指针及引用是在C++中有的,JAVA中没有。JAVA中取消了对内存的操作,随之而来的事也取消了操作符重载的操作。只是在稍候我还是会介绍一
些操 作符重载的功能等。引用主要还是用在函数參数的传递上。所以我在这里就不做过多的介绍了。他们非常有用,有兴趣的同学能够參阅C++
相关书籍。
1.4 运算符及控制语句:
还是自己看看相关书籍吧,这里就不再熬述了!
2.深入探讨面向对象:
2.1“类型”的内部细节:
有了上面的知识,我们如今就行深入的挖掘类的内部实现了。全部的知识点我都会环绕着类与对象展开,在此之前,我希望你可以确信对以
上所介绍的基本内容已全然掌握了!
是的,面向对象的编程语言最大的特色就是能够编写自己所需的数据类型,以更好的解决这个问题。我想我必需要帮你搞清楚“类,对象,属性,
方法它们之间的关 系”!就像我前面所说的,人这个“类”是什么也做不了的,由于“人类”仅仅是一个抽象的概念,它不是实实在在的“东西
”,而这个“东西”就是所谓的对象。仅仅 有人这个“对象”才干去工作。而类呢?类是对象的描写叙述!对象从类中产生出来!此时,对象具有类
所描写叙述的全部的属性以及方法。-------一定要理解这句 话!!!
或许你已经有些不知所措了,没关系!好好的回味一下,我再举个样例!比如电视机,电视机都有工作原理图,那么什么叫电视机呢?仅仅要它
可以实现工作原理图的 全部功能的物体,我们都叫它电视机。你想想是不是这么一回事儿?但是,电视机原理图是不能工作的,也就是这个原
理图不能收看节目,仅仅有电视机这个“实体 ——即所谓的对象”才干收看节目,也就是说,从类生成出对象之后才算得上是真正的有意义!才
能開始工作。此时,电视机拥有电视原理图所描写叙述的全部的属性及 方法!明确了吧,呵呵!
我先前介绍过,类是属性与方法的集合。而这些属性与方法能够被声明为私有的(private),公共的(public)或是受保护(protected)的,他
们描写叙述了对类成员的訪问控制。以下我分别做一下介绍:
1. 公共的(public):把变量声明为公共类型的之后,那么就能够通过对象来直接訪问,一切都是暴露无遗的!也就是说,你的信用卡password
别人也可以直接得到。
2. 私有的(private):假设把变量声明为私有的情况就好多了,想要得到我的信用卡password,对象必需要调用专用的方法才可以得到。
3. 受保护的(protected):介绍继承时再讨论。
4. 默认控制訪问符(friendly)://JAVA中有而C++中没有。
为了实现数据的封装,提高数据的安全性,我们通常会把类的属性声明为私有的,而把类的方法声明为公共的。这样,对象可以直接调用类中
定义的全部方法,当对 象想要改动或得到自己的属性的时候就必需要调用以定义好的专用的方法才可以实现。你想想,你会把你的信用卡password
发布出来嘛?呵呵!所以,我们提倡的是: “对象调方法,方法改属性”;
2.2通过实例看内存分配:
说了这么多,让我们来看一个实例吧!比方:如今我们要编写某家公司员工管理系统,你觉得最合适的数据类型是什么?我觉得是员工个人!
可是在面向过程的 语言中,这样做是不同意的,由于它仅仅能使用语言中的内部数据类型!而员工不在这个内部数据类型之内!或许有人会说可
以用C语言中的struct,好注意! 毕竟它是类的基础!假设你曾经是一名面C或B的程序猿,请你忘掉这些,让我们一起看看怎样用类来实现这
一切吧!
某家公司的员工是人类的一个特殊群体,它除了具备人类的全部特性与方法外,它还有额外的特性与方法,比方她有她的工资、信用卡password、
作息时间等等,这 些特性以及工作内容,工作量等等这些方法。而在计算机中我们该怎样定义这个类呢?以下我将写出它的格式,让你看看在
计算机中它是张什么样子的!
/*在此我须要再次声明的是,我用的是JAVA格式,在语法格式上它与C++大不同样!很多细节以及内部操作都有诸多差别,而在思想上确实大同
小异的*/
//employee.java
public class employee{
private String name; //员工姓名
private int age; //员工年龄
private char sex; //员工性别
private float emolument; //员工薪水
private boolean lunch; //员工午餐
//……等等
public void heater(){ //这种方法是用来加工员工的午餐
lunch = true;
}
public void setName(String a){ //这种方法是改动员工的姓名
name= a;
}
public String getName(){ //这种方法是得到员工的姓名
return name;
}
//……等等
}
这样我们就定义完了我们所须要的数据类型。如今,让我们来看看它可以干什么以及怎么工作!
我想要做的是,工作室里有一个光杆司令叫“jingwei”,我改动它的名字后对对它进行输出,看看我是怎么做的吧!
注意:请细致观察对象是怎样调用方法的,它使用了“.”操作符!其实是这种,对象调用公共的属性或方法时就会使用“.”操作符。
然而在C++中,假设定义一个同类型的指针,该指针调用此对象的方法时,就会使用“->”操作符。更具体的内容清參阅相关书籍了!
//workstation.java
import java.awt.Graphics;
import java.applet.Applet;
public class workstation extends Applet{
private employee jingwei ; //对象的声明,此时并不分配内存!
public void init(){
jingwei = new employee(); /*此时创建对象会调用构造函数,稍候介绍*/
jingwei.setName(“jw”); //设置我的名字
}
public void paint(Graphics g){
g.drawString("my age is "+jingwei.getName(),10,10);//显示我的年龄
}
}
输出结果是:
my name is jw
这串字符串是在输出窗体的x坐标轴为10 px , y坐标轴为10 px的位置。
我如今要做的是,把上面的程序做个大解剖,让你可以看清楚它究竟是怎么一回事儿!(我可不时带你去看里面的汇编,呵呵,那个我也不会
:)
首先还是来看看我们自己定义的数据类型employee,在应用的时候它和int类型的数据没什么两样,一样的须要创建变量(对象),仅仅只是前者是
咱自 己定义的,而后这是它内置的。Employee这个类中有很多属性,也有很多方法。而此时,我们不能直接用我们所创建出来的对象调用它的
属性进行改动。因 为它是private受保护类型的!我要想改动我的姓名我就要用对象调用setName()这种方法,而我想得到我的姓名就要调用
getName()这个 方法。我们全然是依照航线来行走的,这个航线就是“对象调方法,方法改属性”
好的,我真的相信你已经明确了这是怎么一回事儿了!呵呵!仰起航帆,继续前行!
如今让我们一起来看看workstation这个类。这是个主类,和C++中的main()函数的味道差点儿相同。当中,在JAVA中,一个文件仅仅同意有并且必须
有一个主类,这个主类用public来声明!他就跟C++中必需要有一个main()函数是一样的。
让我们来看看这个类中的第一条语句!private employee jingwei ;这条语句的作用是声明一个employee的对象jingwei(在C++中就不用声明
了)。我想要和你说的是“声明”与“定义”之间的差别。声明仅仅是 告诉计算机将要有这种一个变量(对象),在内存中它并不为这个变量
(对象)分配内存!而仅仅有在定义的时候才会给这个变量(对象)分配内存。(须要说明一 下的是init()方法是完毕初始化操作的,在此处定
义对象,为对象分配内存。start()方法用来启动浏览器的主线程,paint()方法来显示 Apple的界面。这些是Applet程序所需的,至于
Application程序就不须要了,当然了,C++中也不须要他们。关于他们的具体内容清參阅 相关书籍)
紧接着就開始定一个对象了,对jingwei这个对象进行操作才会有实际的意义。千万不要有这样的想法:“试图对类进行操作!”就像前面我说的
,电视机 原理不能看电视一样!这是毫无意义的!看这条语句jingwei = new employee();它的意思就是定义一个employee类型的对象jingwei
。此时,我想告诉你的是:“jingwei这个对想拥有了些什 么”。它拥有了类所描写叙述的全部的属性及方法。以下我一一给你列出来:
/*全部的employee对象都拥有这些属性。每创建一个对象就会从新分配一块内存来存放对应对象的这些属性。我的意思是每一个对象都有自己“
独特”的一份*/
private String name; //员工姓名
private int age; //员工年龄
private char sex; //员工性别
private float emolument; //员工薪水
private boolean lunch; //员工午餐
/*全部的employee对象都拥有这些方法。但在内存中仅仅有一份*/
public void heater(){ //这种方法是用来加工员工的午餐
lunch = true;
}
public void setName(String a){ //这种方法是改动员工的姓名
name= a;
}
public String getName(){ //这种方法是得到员工的姓名
return name;
}
/*可是,实际上在创建jingwei这个对象时计算机仅仅给这个对象的全部的属性分配了内存,而并没有给方法分配内存。方法仅仅有一个,是属于所
有的对象的,所以不管创建了多少个对象,计算机仅仅会为一个方法分配一块内存。*/
我想我还是举个样例吧,不然你非晕倒不可。呵呵!
看我这条语句“private boolean lunch;”公司不管午餐,每一个员工都须要带饭。我们如今这样想,公司的空间是全部的内存容量,你的办公
桌就是计算机中的内存中的一部分(每一个员工都有 一份,是在创建对象时分配的)。你把午饭带到了公司,放在了你的办公桌上。“午饭”占
据了你的办公桌的一角(占了你自己“对象”的一块内存容量)。这份午 饭仅仅属于你自己,相同别人的也仅仅属于她自己!所以每一个员工(对象
)都须要一快空间(内存)来存放自己的午餐(属性)。在计算机中也是这种,每创建一个对 象,就会在内存中从新分配一块内存来放“午
餐——lunch”这个属性(对象所拥有的全部的属性)。
计算机仅仅会为对象的属性分配内存。由于每一个对象的都不一样!就像你往公司带的午饭和我往公司带的午饭不一样是一个道理!但方法就不同
了。早晨带的饭中 午就凉了,你须要用微波炉来加热。微波炉可不用你带,公司就有(仅仅占公司的一块空间),它放在了午餐桌上。你想想,
微波炉属于谁的?它属于全部员工的!因 为每一个员工都能够用它。而不必每一个员工都带一份。由此可见,每一个员工(对象)都有一份午饭(属
性),但全部的员工(对象)仅仅一个微波炉(方法)。全部的员 工(对象)都能够通过这个微波炉(方法)来改变自己午餐(属性)的冷热状
态。殊途同归!在计算机中也就是这样,方法仅仅有一份,供全部的对象使用!而属性是 每一个对象一份,由于每一个对象的都不一样。别和我说你
还不明确,不然我会撞墙的,呵呵:)
2.3深入探讨函数:
2.3.1构造函数、默认构造函数、 缺省构造函数
对于上面的实例,它已经能完毕绝大部分工作了,但它还是不完好的,还有许很多多的细节等到我们去完好!或许有的同学已经注意到了,当
我创建完 “jingwei”这个对象时,这个对象的全部的属性都是空的,也就是说:这个对象的姓名是未定的、年龄是未定的、性别是未定的、
薪水是未定的、午餐也是 未定的。而我们想把这些属性都加入上去,就还要用对象调用对应的方法,去一个个改动!天啊,这简直是太麻烦了
!有没有什么好方法可以在我们创建对象的同一时候 就完毕了对属性赋值的操作呢?哦不,应该说是对属性的初始化呢?当然没问题了,这就须要
所谓的构造函数!
构造函数是类中最特殊的函数,它与析构函数的功能正好相反!
从特征上来说:1.它是编程语言中唯一没有返回值类型的函数。
2.它的名称与类的名称必需要全然同样。
3.它必须被声明为公共(public)的类型
4,能够对构造函数进行重载。
5.它在创建对象是自己主动被调用。
从功能上来说:1.它是对类中的属性进行初始化。
事实上,对于上面的程序来说我们没有自定义构造函数。可是,在这样的情况下,系统会自己主动为我们定义一个“默认构造函数”。他会把数值变
量自己主动赋值为0, 把布尔行变量赋值为false等等(但在C++中,默认构造函数不初始化其成员)。假设程序猿定义了构造函数,那么系统就不
会再为你的程序加入一个缺默认 造函数了。(在这里,我们提倡的是自定义构造函数,而不是用系统的默认构造函数)
还是看个实例吧!这样比較清楚一些!
//employee.java
public class employee{
private String name; //员工姓名
private int age; //员工年龄
private char sex; //员工性别
private float emolument; //员工薪水
private boolean lunch; //员工午餐
//……等等
public employee(){ //这个就是“默认”构造函数
name = “jw”; //设置员工姓名
age = 20; //设置员工年龄
sex = “M”; //设置员工性别
emolument = 100; //设置员工薪水
lunch = false; //设置员工午餐
}
public void heater(){ //这种方法是用来加工员工的午餐
lunch = true;
}
//……等等
};
这样,在我们创建“jingwei”这个对象的同一时候,它的全部的属性也被初始化了!显然,这大大的提高了工作效率,可是,它还是不符合要求。
想想看, 假设我们如今创建这个类型的第二个对象的时候会发生什么事情?告诉你,除了对象的“名”(这个名称不在是对象属性中的名称,
而是对象本身的名称)不一样 外,其全部的“属性值”都一样!比方:如今我们创建第二个对象flashmagic,然而我会发现这个对象的全部的
属性和jingwei这个对象的全部的 属性全然同样。而我们仅仅能在用对象的方法去改变着写属性了!非常显然,这样的方法不大好!我们须要一种方
法在创建对象的时候为对象的属性赋予“我们想要的 值”。
相信你也看到了,默认构造函数就显得无能为力了。我们须要的是带參数的构造函数,在创建对象时,我们把參数传给构造函数,这样就能完
成了上述的功能!口说无凭,还是来看个实例吧:
//employee.java
public class employee{
private String name; //员工姓名
private int age; //员工年龄
private char sex; //员工性别
private float emolument; //员工薪水
private boolean lunch; //员工午餐
//……等等
public employee(String n,int a,char s,float e,boolean l){ //看这个构造函数
name = n; //设置员工姓名
age = a; //设置员工年龄
sex = s; //设置员工性别
emolument = e; //设置员工薪水
lunch =l; //设置员工午餐
}
public void heater(){ //这种方法是用来加工员工的午餐
lunch = true;
}
//……等等
};
这样一来,在创建对象的同一时候我们就能够给他赋予我们想要的值,非常显然,这可就方便多了。哦,对了!还没有告诉你怎么创建呢!哈哈,往
前翻几页你会看到这句话:
jingwei = new employee();这是创建一个对象,而我们把它改成
jingwei = new employee("jingwei",20,'M',100,false);这样一来,全部的工作都完毕了,呵呵!(在创建对象的同一时候赋予了我们想要的“初
值”)
2.3.2重载构造函数:
我还是先把概念给你吧,让你有个认识,随后我们在进行论述。
在JAVA中:
1. 函数重载是一个类中声明了多个同名的方法,但有不同的參数个数和參数类型。
2. 函数重构是指在子类中声明与父类同名的方法,从而覆盖了父类的方法。重构攻克了子类与父类的差异问题。(在讨论到继承时我会具体说
明)
在C++中:
1. 数重载的概念一样。
2. 重构的概念可就不一样了,C++中功能更为庞大的虚函数。更具体内容这里就不错过多介绍了!
事实上关于重载的概念你并不陌生,在编程中相信你也接触过。呵呵!让我们来举个操作符重载的样例你就会明确了,(JAVA中不支持这个功能
)我们定义三个整数变量:
int i1=2, i2=3,i3=0;
i3 = i1 + i2;
此时i3=5;加号实现了两个数相加的运算功能。然而我们如今要定义三个字符串变量:
String str1=”jing”, str2=”wei”,str3=””;
str3 = str1 + str2;
此时str3 = “jingwei”;加号实现了两个字符串相加的运算功能。相同是加号,既能够把两个整型的变量加在一起,也能够把两个字符串类型
的变量加在一起。同一个 操作符实现了不同的功能------这就是所谓的操作符重载(嘿嘿,我说你一定见过吧:)!不就好像是汉语中的一词
多意一样!我须要说明一下的是,C++ 中的操作符重载可没有这么简单。比方,我们能够对两个自己定义类型的对象进行相加的运算,进行赋值
的运算。这样书写简洁明了,并且很有用。当然,关于操作 符重载的话题太多了,有兴趣再看看书吧!
我们把操作符的话题在转到函数上来,我们一直强调的是“对象调方法”------对象事实上调的是方法的“名称”。而我们如今要对方法进想重
载,也就是 定义多个同样名称的函数,这样计算机在调用的时候不会混淆嘛?我想应该不会的,呵呵,由于不过函数名称同样,而我们在调
用函数时会把參数传递给他的。既 是没有參数也是一种參数传递參数的信息(信息为无參数)!然而因为參数类型、參数数量、返回值类型不
同我们就能够对同样名称的函数进行区分