面向对象读书笔记

来源:互联网 发布:网络风油精什么意思 编辑:程序博客网 时间:2024/05/22 09:41

静态类和非静态类:
静态类(静态属性等)是类所有的,非静态类为类的实例所有的。
静态类是类的所有实例所共享的,无论此类创建了多少实例,静态类在内存中都只开辟了一块存储空间。

Const常量也可以看成这种类型:
public class myClass{
 public const string KISS_MY_CLASS = "Oh, please kiss the class."; 
}
调用时可以直接myClass.KISS_MY_CLASS

类的声明类型:
protected: 可以在派生的子类中访问的
internal:只有其所在类才可以访问(?)
abstract:不允许直接被实例化的类
sealed:不允许被继承的类

方法的声明类型:
virtual:抽象类里必须的虚拟方法,以此来表明此类为一个抽象类
sealed:不允许被继承的方法
override:多态的一种,覆盖,可以在直接使用父类的该方法base.xxx(e)的前提下,扩展自己的方法.
abstract:简单的定义一个类型,需要派生类具体来实现的抽象方法
extern:简单的定义一个类型

方法的参数类型:
值参:以此方法传递参数的,会copy一份相同值传入方法内部
引用参:ref int param1 直接将传递参数的实际值的地址传入方法,而不会开辟新的存储空间。param1需要被初始化
输出参:out int param2 与ref不同的是,param2不需要被初始化,其它与ref相同
数组参:params int param3[] 数组参必须位于参数列表的最后,内存中为参数的最未开辟了一个可变化的数组存储空间,此类参数不允许再带有ref,out

重载:方法名相同,返回类型相同,而参数不同(个数或类型)的多个方法

操作符重载:
操作符重载的需求起于对不同类型的相加的功能扩展,给操作符定义以新的含义,在特定的类上做新的栓释,比如传入字符串,则进行字符串的相加,这和常规的仅限于整型的+是不同的,当然此类需求也可以扩展到业务类的相加。
可被重载的操作符为:
+ - * % / ++ --
true false
<< >> == != > < >= <=
! & | ^ ~ 

重载的方法(比如洛奇升一级的加点,Player为洛奇的玩家对象,我们用重载++来实现升级的新含义)
public static Player operator ++ (Player _p){
 _p.strength += ;
 _p.AP += 3;
 _p.ability += 1;
 return _p;
}
再比如笛卡尔加法:
public static DKR operator + (DKR d1, DKR d2){
 DKR _dkr = new DKR();
 _dkr.x = d1.x + d2.x;
 _dkr.y = d1.y + d2.y;
 _dkr.z = d1.z + d2.z;
 return _dkr; 
}
实现了这种类的相加:) 很好用吧。可以大大扩展我们的常规思维方法。

readonly:只读域只能够在构造函数中进行修改
public static readonly string KISS_MY_CLASS = "Oh, please kiss the class."; 
public const string KISS_MY_CLASS = "Oh, please kiss the class."; 
以上两句可以起到相同的效果
不同的是,const的表达式的值是在编译时生成,而static readonly是在程序运行了之后才会被加载在内存中的。
所以在另一个项目引用此dll时,如果KISS_MY_CLASS修改后,必须重新编译此dll,才能得到新的常量,而如果为static readonly,则不用编译即可以得到修改过的常量值。

事件:Event
我们需要在Button的重载中定义一个事件的类OnDoubleClick()
1. 首先需要声明一个EventHandler的委托类(和abstract类似,只需要声明,不需要实现)
public delegate void EventHandler(object sender,EventArgs e);//定义一个委托的类型,Event为EventHandler
public class Button: Control{
 public event EventHandler DoubleClick; //定义一个事件OnDoubleClick
 protected void OnDoubleClick(EventArgs e){ //用来触发DoubleClick事件
  if (DoubleClick != null){
   DoubleClick(this.e);
  }
 }
}

索引器:
string _name = string[8];
public string this[int index]{
 get{
  return _name[index];
 }
 set{
  _name[index] = value;
 }
}

继承:C#中的继承规则.
1. 继承可传递
2. 派生类应当是对基类的扩展
3. 构造函数与析构函数不能被继承
4. 派生类如果定义了基类的同名成员,则基类的这些成员不能再被访问
5. 派生类可以重载基类的虚方法,虚属性和虚索引器,表现为多态


多态性:polymorphism
同一操作对应不同的对象,有不同的解释产生不同的结果。多态性可以通过重载基类中的虚函数型方法来实现。
重载虚方法,须使用override声明类型,而不能有static,virtual,new的修饰符

抽象类:
抽象类为它的派生类提供了一个公共的"界面",
抽象类的派生类若要实现它父类的方法,则必须使用override来进行覆盖重载,抽象类与接口不同的是它还可以使用非抽象方法,即派生类override它的时候能使用base.xxx();来加入原型的成员,但如果是抽象方法则不能使用base来进行访问。
抽象方法为抽象类中可以被其派生类重载的“界面”
如果在派生类中使用 public abstract override void func();

虚方法和抽象方法的区别:
抽象方法是没有实际方法的界面函数,即只给子类提供了方法定义,需要子类进行实现,而虚方法可以有自己的实现;
实现虚方法时,直接public override void func(),且里面可以用base.xxx()来加载原虚方法的内容,抽象类则不能。
抽象类一定要有一个虚方法,而不需要有抽象方法.

今天又读了一本"Visual C#.NET 技术内幕"的第一部分,有几点对昨天的"面向对象的笔记"有意义的补充,现列出如下:

1. 常量:
数量的值仅可在编译时指定,平时不允许更改,常量并不占用对象的空间,而被编译到需要该常量的可执行代码中。故无法对const前加static的修饰符,它们实际上并不与任何具体的对象有关联。

2. 构造函数:
构造函数寝值设定项不能访问this指针,因为此时this对象还没有创建好.
初始化的顺序:
a. 初始化全部静态字段;
b. 调用静态构造函数
c. 初始化全部实例字段
d. 调用实例构造函数
故需要先对静态的字段进行赋值

3. 虚方法:如public virtual void Bite(){..;}
如果该类的派生类用了new public Bite(){..} (请注意new关键字),在一个方法被声明为new时,编译器将会被告知此方法不会参与到对虚方法的搜索中来,因此即使基类中增加了一个新的虚方法,现有代码也会继续正常工作。

internal的访问级别表示仅可访问封装该成员的程序集内部的类

4. 强制类型转换:
Type1 Type2 _m = (Type2)_m;
在将子类赋给基类引用时,不需要进行强制类型转换,因为子类总是可以取代基类,但相反的过程不成立 -> 即ZteGir继承了DataGrid,则_zgr可以强制转换为DataGrid,但相反则不可以。(当然不可以 - -!谁知道老爸有多少个儿子呢)
除了这种强制转换,还可以as关键字,可以尝试性的进行类型转换而不会引发类型转换的异常(InvalidCastException),如:
ZteGrid _zgr; //ZteGrid继承DataGrid
DataGrid _dgr = _zgr as DataGrid;
//但是其后必须(是必须)判断_dgr被转换的对象是否为null,因为as关键字即使转换失败也不会引发异常,而只是赋予引用一个null,从而可以根据程序来进行捕获
if (_dgr != null){
 ..
}

5. 结构: struct
结构是一种聚合类型,它将多个不同类型的成员组合为一种新的类型。
1). 结构不能被继承,不能继承类和其它结构,但它可以继承接口;
2). 与类的实例不同的是,永远不会在堆中为结构的实例分配内存空间,它们是从堆栈分配内存的。(?堆是何概念? 与堆栈有啥区别)
3). 结构也能有成员函数与构造函数,但注意:结构的构造函数必须包含至少一个参数
4). 结构不允许声明析构函数

6. 枚举:可以避免未强类型的错误,我们可以将session,权限串,类型等写在枚举类里,用Color.Red这样来进行强类型取值。是一种良好的编程习惯。
    枚举项的值是基于int的,且默认从0开始,我们也可以用指定第一个项的值来指定枚举值的开始边界.

7. 获取类型信息:
    is: 检测是否为指定,返回boolean常量 > if (obj is DataGrid){}
    typeof: 检测类型信息,返回System.Type对象 > DataGrid _grid = typeof(DataGrid);
   sizeof: 检测值类型的大小,引用类型的大小无法测定(因其相当于一个函数指针) > int size = sizeof(DataGrid);
  
8. 运算符重载:须成对进行重载,比如你重载了 ==和!= 但没重载Object.Equals和Object.GetHashCode方法,编译器会报警告。
    Object.Equals用来检验引用是否相等(注意会检验引用喔!而不只是值的相等性)
    Object.GetHashCode()是一个哈希运算符组,它能使哈希表和其他类似的集合数据类型正确分配。哈希函数用于快速生成一个与对象的值相对应的数字(HashCode)

原创粉丝点击