关于Unity的C#基础学习(三)
面向对象
一、编码注意
1.每个C#的脚本只有唯一的一个类是继承自MonoBehaviour
2.类的名字要和我们的文件名字一样
3.代码的缩进
个人习惯:在类的内部来访问数据成员/成员函数的时候,用this来修饰,可以更清楚哪些变量是数据成员,哪些是局部变量,哪些是成员函数,哪些不是。其实this可以省略。
二、类的定义
//权限 public(外部),internal(内存) 修饰这个类
1.internal class Person{
}//Person类只能在程序集的内部使用,internal可以被省略
2.public class Person{
}//Person类可以在程序集的外部使用
三、数据成员和公共函数的定义
1.数据成员如果没有权限修饰,则默认是private
2.函数如果没有权限修饰,则默认是private
3.类的内部指的是类的大括号之间
所以的数据和函数,类的内部是可以直接调用的
public:类的内部,外部都可以直接调用。
protected:类的内部,类的子类可以直接调用。类的外部不能调用,
private:类的内部可以直接调用。类的外部不能调用。
四、多态
一个函数多种形态,函数名相同,参数不一样,实际上是两个函数。
private int xpos;
private int ypos;
void setPosition(int x,int y){
this.xpos=x;//个人习惯用this修饰
this.ypos=y;//个人习惯用this修饰
}
void setPosition(Point pt){
this.setPosition(pt.x,pt.y);//个人习惯用this修饰
}
比如有一个父类superClass,它有2个子类subClass1,subClass2。superClass有一个方法func(),两个子类都重写了这个方法。那么我们可以定义一个superClass的引用obj,让它指向一个子类的对象,比如superClass obj = new subClass1();那么我们调用obj.func()方法时候,会进行动态绑定,也就是obj它的实际类型的func()方法,即subClass1的func()方法。同样你写superClass obj = new subClass2();obj.func()其实调用的是subClass2的func()方法。这种由于子类重写父类方法,然后用父类引用指向子类对象,调用方法时候会进行动态绑定,这就是多态。多态对程序的扩展具有非常大的作用,比如你要再有一个subClass3,你需要改动的东西会少很多,要是使用了配置文件那就可以不动源代码了。
五、构造函数
1.在构造实例的时候调用,也就是实例化类的时候会调用,也就是new 的时候会调用。其实平时的语句Person person=new Person();的含义是:类名 引用变量名=new关键词 类的构造函数();
2.没有返回值,有权限修饰,一般权限都是public,如果是private的话就不能在别的类中new
3.对实例的数据成员进行初始化的一个地方
4.如果我们的类里面没有写构造函数,那么系统会自动生成一个默认的构造函数,如果有了构造函数,系统就不会为我们生成默认的构造函数了。
5.构造函数可以有多个,可以多态,根据new的时候构造函数的参数决定调用哪个构造函数
注意:继承自MonoBehaviour的对象千万不要去重载它的构造函数,写好入口内容就行了。
public Person(){
this.Sex=0;
this.name=“”;
this.age=0;
}
public Person(string name,int age,int sex){
this.sex=sex;
this.name=name;
this.age=age;
}
例子
Person person;//在栈上面定义一个局部的引用变量person
person=new Person();//实例化的时候,调用构造函数,这时候根据参数的形式,调用的是没有参数的构造函数
person=new Person("xiaoming",10,0);//这时候根据参数的形式,调用的是有参数的构造函数
六、继承
为什么要有继承?
男人类和女人类,都有一些公共的属性和方法,如果每个类都写一遍,就会造成代码的重复,很不好,这时候就需要继承的概念,就是先实现人类的逻辑属性,然后让男人类和女人类继承自人类,这样男人类不用写人类的代码,只要写好男人的代码就行了,女人类不用写人类的代码,只要写好女人的代码就行了。
父类或基类:男人类继承了/派生自人类,拥有了人类的所有的数据成员和方法
子类或派生类:人类是男人类的父类/基类
注意
1.继承未必可以使用,只能在子类里面使用父类的public,protected修饰的数据成员和方法。
2.继承的时候父类的权限如果是internal,子类也必须是internal。
3.子类的实例在构造的时候,首先会调用父类的构造函数,再调用子类的构造函数
七、重载
子类重新实现了基类有的方法,子类调用基类的同样名字的方法,调用的首先是自己的方法,可以用base.父类的方法名字来强行调用父类方法。这里的自己指的是Man m=new Man();前面那个Man。
1.base.init_person();
直接说明调用的是父类的方法init_person()方法,如果子类非要调用父类的方法,就用这个语句。只能在类的内部使用。
具体使用:
子类中
public void init_test(){
base.init_test();//先做完父类公共的init_test方法中的逻辑,再实现自己子类的相关逻辑。
......
}
2.子类中写this.init_person();
首先会检查子类中是不是有init_person方法,有的话就调用子类的这个方法,没有的话就去父类中去查找,看有没有init_person()方法,如果还没有,就去父类的父类中查找,直到找到为止。
八、虚函数
比喻1:管理者,有一套自己的规则,在这个规则下面有不同的人,遵守这些规则来做自己的事情。相当于A、B、C...继承了这个规则,在这个规则下去完成自己的事情,管理者在这套规则下做的事情,就是向A、B、C...要最终的结果。
管理者说:“我8点钟要你们两个人AB关于这个方案的结果”
A.getResult();
B.getResult();
如果有100个人话,就要一个for循环来一个一个的根据其名字调用相同的方法,很麻烦,而且可能会有新的成员加入,那样for循环的计数又要改变,更加麻烦了,这时候就需要用到虚函数来管理这些子类。
比喻2:Unity中,管理者,有一套自己的规则,就是组件的继承规则及组件父类,用户遵守这个规则来定义自己的组件类,这个组件类被规定几个接口,当用户扩展了这几个接口,写了自己的组件类。
管理者不知道用户有没有扩展,也不知道扩展了哪一个接口,但是他知道,用户遵守了他的规则,继承了他的组件基类,这时候就需要用到虚函数来管理这些子类。
怎么管理呢?
1.用基类的引用变量来保存子类的实例。用人来保存男人这个实例一样。
一个节点可能挂载很多的组件,比如挂很多的脚本组件,但是管理者不会管你到底是什么具体的脚本名字,内容。他只知道,脚本继承了MonoBehaviour,于是用一个基类的引用变量MonoBehaviour m去调用子类的实例。子类的实例其实也是基类的属性。
Person p=new Man();
p.getResult();
2.面对可能新加入的未知的子类,我们整个管理层要提出一种统一的管理方法,统一管理组件的方法,这个方法可以基于接口来进行提出,也就是说,基类定义这个函数的接口,子类自己去重载,然后做不同的实现。
父类里面写:
Person p=new Man();
p.getResult();//这里会看父类有没有这个函数,如果没有就去看它自己的父类,结果看到有这个函数,还是个虚函数。
public virtual void getResult(){
}//如果遇到一个函数是虚函数,那么就会基于这个实例来查找子类有没有重载这个虚函数,如果有,调用子类的重载函数
子类里面写:
public override void getResult(){
}//显示地表示这个函数是重写父类虚函数的。
这样,就可以用12点方法很好的管理子类以及新进来的子类,简单来说就是,先把所有人都看成一样的,让所有人来重写某个函数,我管理者只要用普遍实例来调用这个公共重写的函数就可以得到各个实例关于这个函数的各自的逻辑实现。事先不知道到底是哪些类的实例,但是我想执行他们各自的逻辑。
a.深入实例:
父类中:
void test_virtual_func(Person p){
p.getResut();
}
public virtual void getResult(){
}
this.test_virtual_func(new Man());
this.test_virtual_func(new Woman());
...
子类中:
public override void getResult(){
}
b.虚函数原理:
1.每个类一旦有重写什么虚函数,就会生成一个虚函数表,类的一个隐形的属性引用变量指向表
2.表内记载了每个类各个虚函数的重写函数代码的地址
3.每个类的实例都有一个隐形的属性引用变量,指向虚函数表
4.所以,在new的时候,就已经把表确定下来了
5.当我们去调用基类中的虚函数的时候,它就先找实例所指向的那个虚函数表,查到重写函数的地址
6.找到重写的函数代码并调用
关于Unity的C#基础学习(三)的更多相关文章
- Python入门基础学习 三
Python入门基础学习 三 数据类型 Python区分整型和浮点型依靠的是小数点,有小数点就是浮点型. e记法:e就是10的意思,是一种科学的计数法,15000=1.5e4 布尔类型是一种特殊的整形 ...
- Python基础学习三
Python基础学习三 1.列表与元组 len()函数:可以获取列表的元素个数. append()函数:用于在列表的最后添加元素. sort()函数:用于排序元素 insert()函数:用于在指定位置 ...
- Django基础学习三_路由系统
今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...
- Java基础学习(三)—面向对象(上)
一.理解面向对象 面向对象是一种思想,是基于面向过程而言的,就是说面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节:这种思想是将数据作为第一位,而方法或者说是 ...
- salesforce lightning零基础学习(三) 表达式的!(绑定表达式)与 #(非绑定表达式)
在salesforce的classic中,我们使用{!expresion}在前台页面展示信息,在lightning中,上一篇我们也提及了,如果展示attribute的值,可以使用{!v.expresi ...
- JAVA多线程基础学习三:volatile关键字
Java的volatile关键字在JDK源码中经常出现,但是对它的认识只是停留在共享变量上,今天来谈谈volatile关键字. volatile,从字面上说是易变的.不稳定的,事实上,也确实如此,这个 ...
- 关于Unity的C#基础学习(四)
一.数组 存放同种类型的一组数据,同类+多个 1.定义 int [] int_set; int_set=new int[10]; //在堆上分配出10个int,int_set是数组的引用变量,指向1 ...
- 关于Unity的C#基础学习(二)
一.Debug的使用 int a=3; Debug.Log("a="+a); 二.整数的定义 int m; Debug.Log(m); //C#比C更严谨,没有初始化的变量打印出 ...
- Oracle 数据库基础学习 (三) Oracle 四个表结构
Oracle 四个表的 emp dept salgrade bunus 的结构,记住有利于后期SQL语句的学习 雇员表(emp) No. 字段 类型 描述 1 empno NUMBER(4) 表示 ...
随机推荐
- ImageResizer for .net 图片处理强大类库
http://imageresizing.net / 官网 http://imageresizing.net/docs/basics (文档) 变换尺寸,加边框,覆盖文本,和旋转和分割图象
- Python 正则表达式学习摘要及资料
来源:Michael_翔_ 摘要 在正则表达式中,如果直接给出字符,就是精确匹配. {m,n}? 对于前一个字符重复 m 到 n 次,并且取尽可能少的情况 在字符串'aaaaaa'中,a{2,4} 会 ...
- EL函数库
一.EL函数库介绍 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用. 这些EL函数在JSTL开发包中进行描述,因此在JSP页 ...
- mysql 禁制远程连接
改表法:把host地址改为% use mysql; update user set host = '%' where user = 'root'and host="127.0.0.1&quo ...
- MySQL数据库字符集由utf8修改为utf8mb4一例
对于mysql 5.5 而言,如果不设定字符集,mysql默认的字符集是 latin1 拉丁文字符集: 为了统一管理和应用开发的方便,一般都会统一将操作系统,客户端,数据库各方面的字符集都设置为 ut ...
- Python-多线程学习总结
我们在做软件开发的时候很多要用到多线程技术.例如如果做一个下载软件象flashget就要用到.象在线视频工具realplayer也要用到因为要同时下载media stream还要播放.其实例子是很多的 ...
- Cocos2d-x3.0 载入Cocostudio的UI后,button无法点击的解决方法
原帖地址:http://blog.csdn.net/musicvs/article/details/28390617 近期发现不少朋友都遇到这个问题,用Cocostudio的UI编辑器创建好UI后,在 ...
- 为MFC中的ListBox添加水平滚动条
我们知道,MFC中的水平滚动条并不像垂直滚动条那样的智能.当文字超出ListBox的宽度时,水平滚动条并不会自己出现,我们需要手动的调用CListBox中的函数SetHorizontalExtent设 ...
- Python zfill() 方法
描述 Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0. 语法 zfill()方法语法: S.zfill(width) 参数 width -- 指定字符串的长度.原字 ...
- AutoFac文档7(转载)
目录 开始 Registering components 控制范围和生命周期 用模块结构化Autofac xml配置 与.net集成 深入理解Autofac 指导 关于 词汇表 适配器 和 装饰器 A ...