关于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) 表示 ...
随机推荐
- UNIX网络编程读书笔记:套接口选项
概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...
- JS生成EXCEL(Chrome浏览器)
直接使用js+Html生成excel文件,当前版本:chrome浏览器 <!DOCTYPE html> <html> <head> <meta charset ...
- Xcode 打包 ipa 包
原地址:http://zengwu3915.blog.163.com/blog/static/27834897201362831449893/ 上次介绍了木有证书的打包ipa.如果安装证书后,我们还有 ...
- 浅析C++中的this指针
转自:http://blog.csdn.net/starlee/article/details/2062586 有下面的一个简单的类: class CNullPointCall { public: s ...
- PHP-"php://(类型)"访问各个输入/输出流以及全局变量$HTTP_RAW_POST_DATA讲解
$_POST $HTTP_RAW_POST_DATA php://input 先来讲以上三者的区别: $_POST:以关联数组方式组织提交的数据, 并对原数据进行编码处理(urldecode)和编码转 ...
- [Asp.net]Calendar+JqueryUi实现日程管理——添加日程
引言 之前在博客园里看到一篇文章,介绍的云日程,所以就一直在想如果是自己该如何实现,所以就自己尝试弄了一个简单的demo. 项目 效果图 日历控件,本来想弄一个js版的,后来考虑,js版的会花费更多的 ...
- MS SQL自定义函数IsPositiveInteger MS SQL自定义函数IsNumeric 水晶报表使用IEnumerable<T>数据源
MS SQL自定义函数IsPositiveInteger 判断字符串是否为正整数,0开始的的数字不算. SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON ...
- Python 算法(2) 哈夫曼编码 Huffman Encoding
这个问题原始是用来实现一个可变长度的编码问题,但可以总结成这样一个问题,假设我们有很多的叶子节点,每个节点都有一个权值w(可以是任何有意义的数值,比如它出现的概率),我们要用这些叶子节点构造一棵树,那 ...
- python __path__ 变量
今天在读django源码的时候遇到了一个问题!它就是__path__这个系统变量 一.__path__变更初见: 由__path__这个变量的名字就知道,这个是一个系统变量,不是用户自定义的变量,于是 ...
- jQuery事件:bind、delegate、on的区别
最近在AngularJS的开发中,遇到一个神奇的事情:我们用到livebox来预览评论列表中的图片, 然而评论列表是由Angular Resource动态载入的.不可思议的是,点击这些动态载入的图片仍 ...