日期:2012-07-28  浏览次数:20447 次

10.操作符重载
     利用操作符重载机制,程序员可以创建让人感觉自然的好似简单类型(如int、long等等)的类。C#实现了一个C++操作符重载的限制版,它可以使诸如这样的精辟的例子—复数类操作符重载表现良好。
     在C#中,操作符==是对象类的非虚的(操作符不可以为虚的)方法,它是按引用比较的。当你构建一个类时,你可以定义你自己的==操作符。如果你在集合中使用你的类,你应该实现IComparable接口。这个接口有一个叫CompareTo(object)方法,如果“this”大于、小于或等于这个object,它应该相应返回正数、负数或0。如果你希望用户能够用优雅的语法使用你的类,你可以选择定义<、<=、>=、>方法。数值类型(int、long等等)实现了IComparable接口。
     下面是一个如何处理等于和比较操作的简单例子:
public class Score : IComparable
{
    int value;
    public Score (int score)
    {
        value = score;
    }
    public static bool operator == (Score x, Score y)
    {
        return x.value == y.value;
    }
    public static bool operator != (Score x, Score y)
    {
        return x.value != y.value;
    }
    public int CompareTo (object o)
    {
        return value - ((Score)o).value;
    }
}
Score a = new Score (5);
Score b = new Score (5);
Object c = a;
Object d = b;
按引用比较a和b:
System.Console.WriteLine ((object)a == (object)b; // 结果为false
【译注:上句代码应该为:System.Console.WriteLine ((object)a == (object)b); // 结果为false】
比较a和b的值:
System.Console.WriteLine (a == b); // 结果为true
按引用比较c和d:
System.Console.WriteLine (c == d); // 结果为false
比较c和d的值:
System.Console.WriteLine (((IComparable)c).CompareTo (d) == 0); // 结果为true
你还可以向Score类添加<、<=、>=、>操作符。C#在编译期保证逻辑上要成对出现的操作符(!=和==、>和<、>=和<=)必须一起被定义。
11.多态
     面向对象的语言使用虚方法表达多态。这就意味着派生类可以有和父类具有同样签名的方法,并且父类可以调用派生类的方法【译注:此处应该是对象(或对象引用、指向对象的指针)】。在Java中,缺省情况下方法就是虚的。在C#中,必须使用virtual关键字才能使方法被父类调用。
     在C#中,还需要override关键字以指明一个方法将重载(或实现一个抽象方法)其父类的方法。
Class B  //【译注:应为class B】
{
    public virtual void foo () {}
}
Class D : B //【译注:应为class D : B】
{
    public override void foo () {}
}
试图重载一个非虚的方法将会导致一个编译时错误,除非对该方法加上“new”关键字,以指明该方法意欲隐藏父类的方法。
Class N : D //【译注:应为class N : D】
{
    public new void foo () {}
}
N n = new N ();
n.foo(); // 调用N的foo
((D)n).foo(); // 调用D的foo
((B)n).foo(); // 调用D的foo
和C++、Java相比,C#的override关键字使得阅读源代码时可以清晰地看出哪些方法是重载的。不过,使用虚方法有利有弊。第一个有利点是:避免使用虚方法轻微的提高了执行速度。第二点是可以清楚地知道哪些方法会被重载。【译注:从“不过”至此,这几句话显然不合逻辑,但原文就是如此:“However, requiring the use of the virtual method has its pros and cons. The first pro is that is the slightly increased execution speed from avoiding virtual methods. The second pro is to make clear what methods are intended to be overridden.”。我认为,若将被我标为斜体的method改为keyword的话,逻辑上会顺畅些。这样,第一句话就可认为是和Java比,因其方法缺省是虚的,第二句话主要就是和C++比,原因参见我后面的相关注释】。然而,利也可能是弊。和Java中缺省忽略final修饰符【译注:在Java中可利用final关键字,对方法上锁,相当于C#/C++中没有用virtual关键字修饰方法/成员函数的情况】以及C++中缺省忽略virtual修饰符相比,Java中缺省选项【译注:即虚的】使得你程序略微损失一些效率,而在C++中,它可能妨碍了扩展性,虽然这对基类的实现者来说,是不可预料的。
【译注:“而在C++中,它可能妨碍了扩展性”这句话或许该这么理解:
class ParentCls
{
public:
     virtual void f();   
};
/////////////////////////////////////////////////////////////////////////////
class ChildCls : public ParentCls
{
public:
     /*virtual*/ void f();/* 此处不标明为virtual的也是virtual的,但是GrandChildCls并不知道(假定GrandChildCls看不到ParentCls),它不知道应该对该方法overload(当然C++中并overload关键字,它是Object Pascal的,这儿再插一句话,overload和override两词翻译都一直都很混乱,Borland官方中文简体手册上都翻译成“重载”)还是override,还是不能碰。即它不知道多态机制在此是否会发生作用。或许你会说,试试不就知道啦