Advanced Class Programming
面向对象的程序设计的魅力来源是类之间的关系.要创造一个类,你所需要的是在类中定义合适的变量和合适的属性.
在ASP.NET程序中,你可以发现一些特殊的类,他们的名字是collections,这些类的功能是收集整理各种各样的对象.某些collections类允许你分类和以唯一的名称检索对象.
Inheritance
继承是代码重用的一种编程方式.他允许一个类获得和扩展另一个类的方法,例如,创造一个TaxableProduct类继承Product类.TaxableProduct类可以获得Product类的所有的方法,属性,事件.同时,你也可以在TaxableProduct类中加入额外的成员.代码示例如下:
public class TaxableProduct : Product
{
private decimal taxRate = 1.15M;
public decimal TotalPrice
{
get{return (Price * taxRate);}
}//因为继承的关系,代码可以访问Price属性,还有一点是由于
//Price属性是基类Product的一个public部分,但是代码却不能
//访问私有变量price,因其是private.
}
这种技术实际上非常的有用.通常在一个应用程序中,大部分的类使用自定义的方式和其他关系来代替继承.因为继承方式会使编程变得复杂,虽然他有许多的优点.
实际上,你会看到继承在每个ASP.NET程序中都存在.继承方式,可以让你定义一个从.NET类库中继承的用户类,例如,当你做了一个用户WEB界面,实际上你是继承了Page基类获得的标准方法,相同的,当你做了一个web服务,你是从WebService类中继承的.
还有许多细节上的问题,我想在实际操作中才能加深理解,加深印象.在此就不一一解释了.
Static Members
在此章的开始,介绍了static属性和方法,即使没有定义一个对象,他们也是可以被使用的.这正如前面所讲的static和instance两种不同的使用方式,static方式有Math.Sqrt(),instance方式有,MyValue.ToString().
Static成员有着许多的用途.有时他们为类提供最基础的转换和函数,要使用static成员的时候,你只需要把static关键字放到访问修饰符的后面就可以了.
下面的例子显示一个TaxableProduct类,此类包含了TaxRate属性,和私有变量.这意味着,这里有一个tax rate信息的备份,并且可以将之用于所有的TaxableProduct类:
public class TaxableProduct : Product
{
private static decimal taxRate = 1.15M;
public static decimal TaxRate
{
get{return taxRate;}
set{taxRate = value;}
}//现在你可以在没有定义一个对象的情况下使用TaxableProduct.TaxRate属性
}//因为我们定义的TaxRate属性是static的.例如TaxableProduct.TaxRate = 1.24M;
Static数据没有被绑定到一个活动的对象当中,实际上,他在程序运行的时候就会存在,这意味着他将是一个全局的变量,static成员不能访问instance成员,如果要访问一个nonstatic成员,他需要一个实例化的对象.
Casting Objects
对象可以使用,与简单数据类型相同的语法,来转换.一个对象只能被转换成三个:他自己,继承,他所继承的基类.你不能把一个对象转换成字符串或一个整形.
例如,你可以转换TaxableProduct对象到Product对象.这样并不会损失任何信息,但是你再也无法访问TotalPrice属性了,除非你把对象再转回去.这强调了一个非常重要的一点,当你转换一个对象的时候,你并没有实际上的改变这个对象.你所改变的是访问数据的权限.换言之,你没有改变对象,你只改变了对象某些部位的可见性.
例如,如果你有一个Product变量引用了TaxableProduct对象,实际上你的对象是TaxableProduct对象,但是,你只能使用Product定义的属性,方法.
下面的例子创造了一个TaxableProduct对象,转换他到一个Product的引用,然后检测对象是否能被安全的转换回去.你将注意到,实际的转换使用的是前面章节讲到的语法.
Product theProduct;
TaxableProduct theTaxableProduct;
//定义两个对象,没有使用关键字new,没有初始化他.
theProduct = new TaxableProduct();
//使用TaxableProduct()初始化他.
if(theProduct is TaxableProduct)//这句是真.
{ theTaxableProduct = (TaxableProduct)theProduct; }
//将theProduct对象转换成TaxableProduct,然后赋予其他的变量.
decimal totalPrice;
totalPrice = theTaxableProduct.TotalPrice;
//这一句可以运行.
totalPrice = theProduct.TotalPrice;
//就算是theTaxableProduct和theProduct是相同的对象,此句也无法运行,
//Product类无法提供一个TotalPrice属性.
在这点上,转换一个对象是一个很特殊的方法,但只允许在继承的时候使用.当你使用特殊且复杂的类的时候,对象转换是有必要的.
前面介绍的ArrayList类,是被设计作为存储任何类型的对象的,具有这个功能,他对待所有的对象以同一种方法--作为系统根的instance方法(需要记住的是所有的类都是继承System.Object的,即使在代码中并没有明确的定义).当你从ArrayList中检索一个对象时,你需要转换他从System.Object到他实际的类型.
ArrayList products = bew ArrayList();
products.Add(product1);
products.Add(product2);
products.Add(product3);
Product retrievedProduct = (Product)products[0];
Respose.Write(retrievedProduct.GetHtml());
Object retrievedObject = products[0];
Respose.Write(retrievedObject.GetHtml());
//这行代码是错误的,这里没有Object.GetHtml()方法.
正如你所看见的,如果你不转换,你不能使用你检索到的对象方法和属性,你会发现在.NET代码中有许多这样的例子,你必须去转换他们到正确的类型,这样你才能使用这个类型全部的成员.
这里的CASTING OBJECT我看得是一头的雾水,有很多地方不理解,也有很多地方不知道该怎么办,光看代码似乎理解了,但是却写不出来,对此还真的是非常的苦恼。
Partial Classes
实际上用此中方法定义类的时候,可以把类定义在不同的文件中,但是在编译的时候将他们编译进一个文件,虽然这并没有非常实际的用途,但是他对于一个大型的工程的类进行分类,方便管理是非常有必要的。例如
public partial class Product 将他们定义在不同的文件中,但是编译的时候会编译进一个文件里。他和在一个文件中定义一个类没有任何实际使用上的区别。
Generics
例如在使用ArrayList的时候,你可以往他里面存如任何的数据,你可以先存入Product对象,然后再存如字符串,这的确提供便利,但是也导致了复杂,他不方便管理,甚至会导致一些无法想象的错误,那么是否可以同一个类的不同对象存入呢?答案是可以的。
使用List<Product> products = new List<Product>();此时往products里面只能存入Product的对象.
此章节我也有很多不理解的地方,特别是casting object这块,不过看完代码了解了一些.我认为看代码才是学习编程的最佳途径,毕竟一些东西只能意会不可言传.