C#轻松入门(四)面向对象的高级编程
2007-06-08 01:08
441 查看
第4章 面向对象的高级编程
封装、继承与多态
版本控制
接口
委托
序列化和反序列化
泛型处理
4.1 封装、继承与多态
封装:隐藏调用者不需要了解的信息。
继承:简化类的设计。
多态:类为名称相同的方法提供不同实现方式的能力。
4.1.1 封装
模块信息通过类封装
类的成员通过字段、属性、方法、事件封装
私有的用private
可以继承的用protected
公共成员用public
不要为了方便把什么都定义成public
不要为了方便把什么都定义成static
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private int number;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int Number
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
get
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return number;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
set
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (value > 0)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
number = value;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//Program.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public class Program
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static void Main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
MyClass me = new MyClass();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
me.Number = -1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine(
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
"Number:{0}", me.Number);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.ReadLine();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
回答:既然没有赋值,为什么输出0?
4.1.2 继承
两种实现继承的方式:类继承和接口继承。
类继承只允许单一继承 ,接口可实现多重继承。
被继承的类叫基类
继承自其他类的类叫扩充类
声明扩充类的语法:
[访问修饰符] class 扩充类名称:基类名称
{
//程序代码
}
扩充类继承了所有定义在基类中数据的定义和方法。但是不继承构造函数,而且扩充类不继承基类的数据值。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyNewClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyNewClass : MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private string str = "hello";
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public void Hello()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Number = 2;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine(str);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
4.1.3 多态性
多态性是指类为名称相同的方法提供不同实现方式的能力。利用多态性,就可以调用类中的某个方法而无需考虑该方法是如何实现的。
有以下几种实现多态性的方式。
第一种方式是通过继承实现多态性。
第二种方式是通过抽象类实现多态性。
第三种方式是通过接口实现多态性。
1. 虚拟方法
在基类中,如果想让某个方法或者事件被扩充类重写
,可以使用修饰符virtual表明:
public virtual void myMethod()
{
……//程序代码
}
扩充类则用override重写:
public override void myMethod()
{
……//程序代码
}
使用虚拟方法与重写方法时,需要注意下面几个方面:
1) 虚拟方法不能声明为静态(static)的。因为静态的方法是应用在类这一层次的,而多态性只能在对象上运作。
2) virtual不能和private一起使用。因为声明为private就无法在扩充类中重写了。
3) 重写方法的名称、参数个数、类型以及返回值都必须和虚拟方法的一致。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public virtual void Hello()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("123");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyNewClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyNewClass : MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private string str = "hello";
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public override void Hello()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Number = 2;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine(str);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
2. 隐藏基类的方法
在扩充类中,可以使用new关键字来隐藏基类的方法,即使用一个完全不同的方法取代旧的方法。
与方法重写不同的是,使用new关键字时并不要求基类中的方法声明为virtual,只要在扩充类的方法前声明为new,就可以隐藏基类的方法。
3. 抽象类
抽象类使用abstract修饰符,用于表示所修饰的类是不完整的,即类中的成员(例如方法)不一定全部实现,可以只有声明没有实现。抽象类只能用作基类。抽象类与非抽象类相比有以下主要不同之处:
第一是抽象类不能直接被实例化,只能在扩充类中通过继承使用,对抽象类使用new运算符会产生编译时错误
第二个不同点是抽象类可以包含抽象成员,而非抽象类不能包含抽象成员。当从抽象类派生非抽象类时,这些非抽象类必须具体实现所继承的所有抽象成员。
4.2 版本控制
用C#编写方法时,如果在扩充类中重写基类的方法,需要用override
声明;要隐藏基类的方法,需要用new声明,这就是C#进行版本控制的依据。
在C#中,所有的方法默认都是非虚拟的,调用非虚拟方法时不会受到版本的影响,不管是调用基类的方法还是调用扩充类的方法,都会和设计者预期的结果一样执行实现的程序代码。
相比之下,虚拟方法的实现部分可能会因扩充类的重写而影响执行结果。也就是说,在执行时期调用虚拟方法时,它会自动判断应该调用哪个方法。
4.3 接口
接口的主要特点是只有声明部分,没有实现部分。
接口成员的实现是通过类完成的。
定义在接口中的方法都是public的。
使用interface关键字声明一个接口。常用的语法是:
[访问修饰符] interface 接口名称
{
// 接口体
}
一般情况下,以大写的“I”开头指定接口名,表明这是一个接口。
需要在不相关的类中实现同样的功能时,可以使用接口。
4.4 委托
委托的特点是可以将方法作为参数传递。
就像A(方法)委托B(delegate)完成一些事(把方法当作参数传递给B),你如果想找A做什么事(想调用方法A),而A这时候正在忙(系统不允许在这种情况下调用方法A),但是你可以告诉B(可以调用委托B),其最终效果和告诉A一样(调用委托B和调用方法A效果相同)。但是区别是B可以在他认为合适的时候再告诉A(委托可以等某些条件满足时再调用方法A)。而B什么时候告诉A,你就不用操心了。
这种机制是异步操作以及事件处理的基础。
在这一章抽象的讲代码不容易理解,等第15章以后再结合具体应用介绍如何实现。
4.5 序列化与反序列化
序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。两个过程结合可以存储和传输数据。
.NET Framework 提供两种序列化技术:
1) 二进制序列化
这种序列化可以保持类型不变,即可以在应用程序的不同调用之间保留对象的状态。
2) XML和SOAP序列化
这种序列化仅序列化公共属性和字段,不保存类型。
4.6 泛型处理
泛型(Generic)一般用在集合和在集合上运行的方法中。.NET框架
2.0以前的版本不支持泛型。
使用泛型具有以下明显的优点:
1)可以避免以下两个问题:内部实现代码冗余和困扰开发人员的含混不清的编译器错误提示;
2) 类型安全;
3)二进制代码重用;
4)性能;
5)清晰性。
常用泛型
凡是有对应泛型类型的类就尽量不要使用早期提供的非泛型类型的类。下面的泛型类型对应于低版本提供的类型:
泛型类 低版本提供的非泛型类
List<> ArrayList
Dictionary<> Hashtable
Queue<> Queue
Stack<> Stack
SortedList<> SortedList
实验中用到的泛型
SortedList<> :按键排序的键值对集合,是运算复杂度为 O(log n) 的二进制搜索树 。
常用方法:
Add方法:将带有指定键和值的元素添加到SortedList<> 中
例如(注意:如果插入重复的键会产生异常):
SortedList<string, string> openWith = new SortedList<string, string>();
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
TryGetValue方法:获取与指定的键相关联的值 。
例如:
string value = "";
if (openWith.TryGetValue("tif", out value))
{
Console.WriteLine("For key = /"tif/", value = {0}.", value);
}
else
{
Console.WriteLine("Key = /"tif/" is not found.");
}
ContainsKey 方法:确定 SortedList<>中 是否包含指定的键。
例如:
if (!openWith.ContainsKey("ht"))
{
openWith.Add("ht", "hypertrm.exe");
Console.WriteLine( "Value added for key = /"ht/": {0}", openWith["ht"]);
}
Remove 方法:从SortedList<> 中移除带有指定键的元素。
例如:
openWith.Remove("doc");
if (openWith.ContainsKey("doc") == false)
{
Console.WriteLine("Key /"doc/" is not found.");
}
封装、继承与多态
版本控制
接口
委托
序列化和反序列化
泛型处理
4.1 封装、继承与多态
封装:隐藏调用者不需要了解的信息。
继承:简化类的设计。
多态:类为名称相同的方法提供不同实现方式的能力。
4.1.1 封装
模块信息通过类封装
类的成员通过字段、属性、方法、事件封装
私有的用private
可以继承的用protected
公共成员用public
不要为了方便把什么都定义成public
不要为了方便把什么都定义成static
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private int number;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public int Number
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
get
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
return number;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
set
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
if (value > 0)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
number = value;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//Program.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public class Program
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public static void Main()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
MyClass me = new MyClass();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
me.Number = -1;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine(
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
"Number:{0}", me.Number);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.ReadLine();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
回答:既然没有赋值,为什么输出0?
4.1.2 继承
两种实现继承的方式:类继承和接口继承。
类继承只允许单一继承 ,接口可实现多重继承。
被继承的类叫基类
继承自其他类的类叫扩充类
声明扩充类的语法:
[访问修饰符] class 扩充类名称:基类名称
{
//程序代码
}
扩充类继承了所有定义在基类中数据的定义和方法。但是不继承构造函数,而且扩充类不继承基类的数据值。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyNewClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyNewClass : MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private string str = "hello";
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public void Hello()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Number = 2;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine(str);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
4.1.3 多态性
多态性是指类为名称相同的方法提供不同实现方式的能力。利用多态性,就可以调用类中的某个方法而无需考虑该方法是如何实现的。
有以下几种实现多态性的方式。
第一种方式是通过继承实现多态性。
第二种方式是通过抽象类实现多态性。
第三种方式是通过接口实现多态性。
1. 虚拟方法
在基类中,如果想让某个方法或者事件被扩充类重写
,可以使用修饰符virtual表明:
public virtual void myMethod()
{
……//程序代码
}
扩充类则用override重写:
public override void myMethod()
{
……//程序代码
}
使用虚拟方法与重写方法时,需要注意下面几个方面:
1) 虚拟方法不能声明为静态(static)的。因为静态的方法是应用在类这一层次的,而多态性只能在对象上运作。
2) virtual不能和private一起使用。因为声明为private就无法在扩充类中重写了。
3) 重写方法的名称、参数个数、类型以及返回值都必须和虚拟方法的一致。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public virtual void Hello()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine("123");
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
//MyNewClass.cs
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
using System;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
namespace ConsoleTest
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
class MyNewClass : MyClass
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private string str = "hello";
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public override void Hello()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Number = 2;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Console.WriteLine(str);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
}
2. 隐藏基类的方法
在扩充类中,可以使用new关键字来隐藏基类的方法,即使用一个完全不同的方法取代旧的方法。
与方法重写不同的是,使用new关键字时并不要求基类中的方法声明为virtual,只要在扩充类的方法前声明为new,就可以隐藏基类的方法。
3. 抽象类
抽象类使用abstract修饰符,用于表示所修饰的类是不完整的,即类中的成员(例如方法)不一定全部实现,可以只有声明没有实现。抽象类只能用作基类。抽象类与非抽象类相比有以下主要不同之处:
第一是抽象类不能直接被实例化,只能在扩充类中通过继承使用,对抽象类使用new运算符会产生编译时错误
第二个不同点是抽象类可以包含抽象成员,而非抽象类不能包含抽象成员。当从抽象类派生非抽象类时,这些非抽象类必须具体实现所继承的所有抽象成员。
4.2 版本控制
用C#编写方法时,如果在扩充类中重写基类的方法,需要用override
声明;要隐藏基类的方法,需要用new声明,这就是C#进行版本控制的依据。
在C#中,所有的方法默认都是非虚拟的,调用非虚拟方法时不会受到版本的影响,不管是调用基类的方法还是调用扩充类的方法,都会和设计者预期的结果一样执行实现的程序代码。
相比之下,虚拟方法的实现部分可能会因扩充类的重写而影响执行结果。也就是说,在执行时期调用虚拟方法时,它会自动判断应该调用哪个方法。
4.3 接口
接口的主要特点是只有声明部分,没有实现部分。
接口成员的实现是通过类完成的。
定义在接口中的方法都是public的。
使用interface关键字声明一个接口。常用的语法是:
[访问修饰符] interface 接口名称
{
// 接口体
}
一般情况下,以大写的“I”开头指定接口名,表明这是一个接口。
需要在不相关的类中实现同样的功能时,可以使用接口。
4.4 委托
委托的特点是可以将方法作为参数传递。
就像A(方法)委托B(delegate)完成一些事(把方法当作参数传递给B),你如果想找A做什么事(想调用方法A),而A这时候正在忙(系统不允许在这种情况下调用方法A),但是你可以告诉B(可以调用委托B),其最终效果和告诉A一样(调用委托B和调用方法A效果相同)。但是区别是B可以在他认为合适的时候再告诉A(委托可以等某些条件满足时再调用方法A)。而B什么时候告诉A,你就不用操心了。
这种机制是异步操作以及事件处理的基础。
在这一章抽象的讲代码不容易理解,等第15章以后再结合具体应用介绍如何实现。
4.5 序列化与反序列化
序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。两个过程结合可以存储和传输数据。
.NET Framework 提供两种序列化技术:
1) 二进制序列化
这种序列化可以保持类型不变,即可以在应用程序的不同调用之间保留对象的状态。
2) XML和SOAP序列化
这种序列化仅序列化公共属性和字段,不保存类型。
4.6 泛型处理
泛型(Generic)一般用在集合和在集合上运行的方法中。.NET框架
2.0以前的版本不支持泛型。
使用泛型具有以下明显的优点:
1)可以避免以下两个问题:内部实现代码冗余和困扰开发人员的含混不清的编译器错误提示;
2) 类型安全;
3)二进制代码重用;
4)性能;
5)清晰性。
常用泛型
凡是有对应泛型类型的类就尽量不要使用早期提供的非泛型类型的类。下面的泛型类型对应于低版本提供的类型:
泛型类 低版本提供的非泛型类
List<> ArrayList
Dictionary<> Hashtable
Queue<> Queue
Stack<> Stack
SortedList<> SortedList
实验中用到的泛型
SortedList<> :按键排序的键值对集合,是运算复杂度为 O(log n) 的二进制搜索树 。
常用方法:
Add方法:将带有指定键和值的元素添加到SortedList<> 中
例如(注意:如果插入重复的键会产生异常):
SortedList<string, string> openWith = new SortedList<string, string>();
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
TryGetValue方法:获取与指定的键相关联的值 。
例如:
string value = "";
if (openWith.TryGetValue("tif", out value))
{
Console.WriteLine("For key = /"tif/", value = {0}.", value);
}
else
{
Console.WriteLine("Key = /"tif/" is not found.");
}
ContainsKey 方法:确定 SortedList<>中 是否包含指定的键。
例如:
if (!openWith.ContainsKey("ht"))
{
openWith.Add("ht", "hypertrm.exe");
Console.WriteLine( "Value added for key = /"ht/": {0}", openWith["ht"]);
}
Remove 方法:从SortedList<> 中移除带有指定键的元素。
例如:
openWith.Remove("doc");
if (openWith.ContainsKey("doc") == false)
{
Console.WriteLine("Key /"doc/" is not found.");
}
相关文章推荐
- C#轻松入门(三)面向对象的编程基础
- C#编程入门10_面向对象之继承
- C#编程入门_面向对象之继承_10
- C#编程入门9_面向对象之封装
- C# for Unity 编程语言快速入门教程(连载4)---C#面向对象OOP编程
- 【C#】C#面向对象OOP编程
- VS2010轻松学习C#-从零到深入-天轰穿.NET4趣味编程视频教程
- C#编程入门与应用Day9
- C++ STL编程轻松入门基础
- C# for Unity 编程语言快速入门教程(连载7)---C#OOP编程之多态性
- 第一章 C#编程入门基础
- 网站安全编程 黑客入侵 脚本黑客 高级语法入侵 C/C++ C# PHP JSP 编程
- C#编程入门13_String类及常用的工具类
- C#编程入门18_进程和线程
- C#编程入门_ToArray和CopyTo的区别_22
- Java 8函数编程轻松入门(五)并行化(parallel)
- JavaScript高级编程入门
- UML之轻松入门(3)-SRP做好厨子,让别人编程去吧
- 无师自通C#.NET和SQL编程入门免费视频教程大全(由吉日嘎拉精心录制,可以改变一个人职业生涯的入门教程)
- 【PHP面向对象(OOP)编程入门教程】2.什么是类,什么是对象,类和对象之间的关系