C#轻松入门(四)面向对象的高级编程

第4章  面向对象的高级编程

封装、继承与多态
版本控制
接口
委托
序列化和反序列化
泛型处理

4.1  封装、继承与多态
封装:隐藏调用者不需要了解的信息。
继承:简化类的设计。
多态:类为名称相同的方法提供不同实现方式的能力。

4.1.1 封装
模块信息通过类封装
类的成员通过字段、属性、方法、事件封装
私有的用private
可以继承的用protected
公共成员用public
不要为了方便把什么都定义成public
不要为了方便把什么都定义成static
// MyClass.cs
using  System;
namespace  ConsoleTest
{
    
class MyClass
    
{
        
private int number;
        
public int Number
        
{
            
get
            
{
                
return number;
            }

            
set
            
{
                
if (value > 0)
                
{
                    number 
= value;
                }

            }

        }

    }

}


// Program.cs
using  System;
namespace  ConsoleTest
{
    
public class Program
    
{
        
public static void Main()
        
{
            MyClass me 
= new MyClass();
            me.Number 
= -1;
            Console.WriteLine(
                
"Number:{0}", me.Number);
            Console.ReadLine();
        }

    }

}

回答:既然没有赋值,为什么输出0?

4.1.2 继承
两种实现继承的方式:类继承和接口继承。
类继承只允许单一继承 ,接口可实现多重继承。

被继承的类叫基类
继承自其他类的类叫扩充类
声明扩充类的语法:
    [访问修饰符] class 扩充类名称:基类名称
    {
           //程序代码
    }
        扩充类继承了所有定义在基类中数据的定义和方法。但是不继承构造函数,而且扩充类不继承基类的数据值。
// MyNewClass.cs
using  System;
namespace  ConsoleTest
{
    
class MyNewClass : MyClass
    
{
        
private string str = "hello";
        
public void Hello()
        
{
            Number 
= 2;
            Console.WriteLine(str);
        }

    }

}

4.1.3 多态性
多态性是指类为名称相同的方法提供不同实现方式的能力。利用多态性,就可以调用类中的某个方法而无需考虑该方法是如何实现的。
            有以下几种实现多态性的方式。
           第一种方式是通过继承实现多态性。
           第二种方式是通过抽象类实现多态性。
           第三种方式是通过接口实现多态性。
1. 虚拟方法
              在基类中,如果想让某个方法或者事件被扩充类重写

,可以使用修饰符virtual表明:
  public virtual void myMethod()
  {
        ……//程序代码
  }
 扩充类则用override重写:
  public override void myMethod()
  {
        ……//程序代码
  }
使用虚拟方法与重写方法时,需要注意下面几个方面:
1) 虚拟方法不能声明为静态(static)的。因为静态的方法是应用在类这一层次的,而多态性只能在对象上运作。
2) virtual不能和private一起使用。因为声明为private就无法在扩充类中重写了。
3) 重写方法的名称、参数个数、类型以及返回值都必须和虚拟方法的一致。
// MyClass.cs
using  System;
namespace  ConsoleTest
{
    
class MyClass
    
{
        
public virtual void Hello()
        
{
            Console.WriteLine(
"123");
        }

    }

}

// MyNewClass.cs
using  System;
namespace  ConsoleTest
{
    
class MyNewClass : MyClass
    
{
        
private string str = "hello";
        
public override void Hello()
        
{
            Number 
= 2;
            Console.WriteLine(str);
        }

    }

}

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.");
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值