1 / 139

第 4 章 面向对象编程进阶

第 4 章 面向对象编程进阶. 4.1 类的继承与多态 当今的面向对象编程语言都提供了继承和多态的功能, C# 作为一种面向对象的高级编程语言也具有这样的特点。继承是面向对象语言的基本特征,是实现代码复用的手段。继承使得在原有的类基础之上,对原有的程序进行扩展,从而提高程序开发的速度,实现代码的复用。同一种方法作用于不同对象可以产生不同的结果,这就是多态性。它是在基类中使用虚方法,在其派生类中使用重载实现的。. 4.1.1 继承. 1. 使用继承

fineen
Download Presentation

第 4 章 面向对象编程进阶

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第4章 面向对象编程进阶 4.1类的继承与多态 当今的面向对象编程语言都提供了继承和多态的功能,C#作为一种面向对象的高级编程语言也具有这样的特点。继承是面向对象语言的基本特征,是实现代码复用的手段。继承使得在原有的类基础之上,对原有的程序进行扩展,从而提高程序开发的速度,实现代码的复用。同一种方法作用于不同对象可以产生不同的结果,这就是多态性。它是在基类中使用虚方法,在其派生类中使用重载实现的。

  2. 4.1.1 继承 • 1. 使用继承 • 继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。使用继承而产生的类被称为派生类或者子类,而被继承的类则称为基类、超类或父类。客观世界中的许多事物之间往往都是具有相同的特征,具有继承的特点。图4.1和图4.2是两个采用类的层次图表示继承的例子。

  3. 1. 使用继承 图4.1 类的层次结构1 图4.2 类的层次结构2

  4. 4.1.1 继承 • 【例4.1】类的继承。 • using System; • //定义基类Shape • public class Shape • { • protected string Color; • public Shape() • {;} • public Shape(string Color) • { • this.Color = Color; • } • public string GetColor() • { • return Color; • } • }

  5. 【例4.1】 • //定义Circle类,从Shape类中派生 • public class Circle : Shape • { • private double Radius; • public Circle(string Color, double Radius) • { • this.Color = Color; • this.Radius = Radius; • } • public double GetArea() • { • return System.Math.PI * Radius * Radius; • } • }

  6. 【例4.1】 • // 派生类Rectangular,从Shape类中派生 • public class Rectangular:Shape • { • protected double Length, Width; • public Rectangular() • { • Length=Width=0; • } • public Rectangular(string Color,double Length, double Width) • { • this.Color = Color; • this.Length = Length; • this.Width = Width; • } • public double AreaIs() • { • return Length*Width; • }

  7. 【例4.1】 • public double PerimeterIs()//周长 • { • return (2*(Length+Width)); • } • } • // 派生类Square,从 Rectangular类中派生 • public class Square: Rectangular • { • public Square(string Color,double Side) • { • this.Color = Color; • this.Length=this.Width = Side; • } • } • public class TestInheritance • { • public static void Main()

  8. 【例4.1】 • { • Circle Cir= new Circle("orange",3.0); • Console.WriteLine("Circle color is {0},Circle area is {1}", • Cir.GetColor(),Cir.GetArea()); • Rectangular Rect= new Rectangular("red",13.0, 2.0); • Console.WriteLine("Rectangualr color is {0},Rectangualr area is {1}, • Rectangular perimeter is {2}", Rect.GetColor(),Rect.AreaIs(), Rect.PerimeterIs()); • Square Squ= new Square("green",5.0); • Console.WriteLine("Square color is {0},Square Area is {1}, Square perimeter is {2}", Squ.GetColor(),Squ.AreaIs(), Squ.PerimeterIs()); • } • } • 运行结果如图4.3所示。 图4.3 运行结果

  9. 4.1.1 继承 • 2. base关键字 • 例4.1程序中的square类也可以改写为: • // 派生类Square,从 Rectangular类中派生 • public class Square: Rectangular • { • public Square(string Color,double Side):base(Color,Side,Side) • { ; } • } • 关键字base的作用是调用Rectangular类的构造函数并将Square类的变量初始化。如果将Square类改写成: • // 派生类Square,从 Rectangular类中派生 • public class Square: Rectangular • { • public Square(string Color,double Side) • { ; } • }

  10. 2. base关键字 • 实际上这种情况调用的是父类的无参构造函数,而不是有参构造函数,等同于: • // 派生类Square,从 Rectangular类中派生 • public class Square: Rectangular • { • public Square(string Color,double Side):base() • { ; } • } • base关键字除了能调用基类对象构造函数,还可以调用基类的方法。在下例中,Employee类的GetInfoEmployee方法使用了base关键字调用基类Person的GetInfoPerson方法。

  11. 2. base关键字 • 【例4.2】base调用基类的方法。 • using System; • public class Person • { • protected string Phone = "444-555-666"; • protected string Name = "李明"; • public void GetInfoPerson() • { • Console.WriteLine("Phone: {0}", Phone); • Console.WriteLine("Name: {0}", Name); • } • } • class Employee : Person • { • public string ID = "ABC567EFG"; • public void GetInfoEmployee()

  12. 【例4.2】 • { • // 调用基类Person的GetInfo方法 • base.GetInfoPerson(); • Console.WriteLine("Employee ID: {0}",ID); • } • } • class TestClass • { • public static void Main() • { • Employee Employees = new Employee(); • Employees.GetInfoEmployee(); • } • }

  13. 4.1.1 继承 • 3. 继承中的构造函数与析构函数 • 在前面讨论过派生类的构造函数会隐式调用父类的无参构造函数。那么,如果父类也是派生于其它类,会是什么样的情形呢?C#的执行顺序是这样的:根据层次链找到最顶层的基类,先调用基类的构造函数,再依次调用各级派生类的构造函数。而析构函数的次序正好相反。 • 【例4.3】继承中的构造函数与析构函数。 • using System; • public class BaseLifeSample • { • public static void Main() • { • Son s1 = new Son(); • } • } • public class Grandsire

  14. 【例4.3】 • { • public Grandsire() • { • Console.WriteLine("调用Grandsire的构造函数"); • } • ~Grandsire() • { • Console.WriteLine("调用Grandsire的析构函数"); • } • } • public class Father : Grandsire • { • public Father() • { • Console.WriteLine("调用Father的构造函数"); • } • ~Father() • { • Console.WriteLine("调用Father的析构函数"); • } • }

  15. 【例4.3】 • public class Son : Father • { • public Son() • { • Console.WriteLine("调用Son的构造函数"); • } • ~Son() • { • Console.WriteLine("调用Son的析构函数"); • } • } • 运行结果如图4.4所示。 图4.4 运行结果

  16. 4.1.1 继承 • 4. System.Object类 • C#所有类都派生于System.Object类。在定义类时如果没有指定派生于哪一个类,系统就默认其派生于Object类。例4.2中Shape的定义就等同于: • public class Shape :System.Object • { • … • } • System.Object类常见的公有方法是: • Equals:如果两个对象具有相同值时,方法将返回true。 • GetHashCode:方法返回对象的值的散列码。 • ToString:通过在派生类中重写该方法,返回一个表示对象状态的字符串。

  17. 4.1.2多态 • 多态也是面向对象语言的基本特征之一,是指在程序执行之前无法根据函数名和参数确定调用哪一个操作,而是程序执行过程中,根据实际运行情况动态确定,从而带来编程高度的灵活性。实现多态的方法是使用虚方法。 • 1. 虚方法的重载 • 在类的方法前加上关键字virtual, 则该方法被称为虚方法。通过对虚方法的重载,实现在程序运行过程中确定调用的方法。需要注意的是这里所讲的重载与第3章所讲的通过参数类型与参数个数的不同实现的重载含义是不同的。 • 【例4.4】虚方法的重载。 • using System; • class A • { • public void F() { Console.WriteLine("A.F"); } • public virtual void G() { Console.WriteLine("A.G"); } • }

  18. 【例4.4】 • class B: A • { • new public void F() { Console.WriteLine("B.F"); } • public override void G() { Console.WriteLine("B.G"); } • } • class Test • { • static void Main() • { • B b = new B(); • A a = b; • a.F(); • b.F(); • a.G(); • b.G(); • } • }

  19. 【例4.4】 • 在A 类定义了提供了非虚的F和虚方法 G, 派生类B 则对方法F实现覆盖,对虚方法G • 实现了虚方法的的重载。“A a = b”实际上a仍旧是一个b对象。输出结果为: • A.F • B.F • B.G • B.G • 在例4.1中计算圆形和矩形的面积分用了两个不同的方法GetArea和AreaIs,也可以通过 • 虚方法实现。将Shape中增加虚方法: • public virtual double GetArea() • { • return 0.0; • } • 在Circle类中对虚方法重载: • public override double GetArea() • { • return System.Math.PI * radius * radius; • } • 在Rectangular类中对虚方法重载: • public override double GetArea() • { • return Length*Width; • }

  20. 4.1.2多态 • 【例4.5】用虚方法的实现重载 • using System; • //定义基类Shape • public class Shape • { • protected string Color; • public Shape() • {;} • public Shape(string Color) • { • this.Color = Color; • } • public string GetColor() • { • return Color; • } • public virtual double GetArea() • { • return 0.0; • } • }

  21. 【例4.5】 • //定义Circle类,从Shape类中派生 • public class Circle : Shape • { • private double Radius; • public Circle(string Color, double Radius) • { • this.Color = Color; • this.Radius = Radius; • } • public override double GetArea() • { • return System.Math.PI * Radius * Radius; • } • } • // 派生类Rectangular,从Shape类中派生 • public class Rectangular:Shape

  22. 【例4.5】 • { • protected double Length, Width; • public Rectangular(string Color,double Length, double Width) • { • this.Color = Color; • this.Length = Length; • this.Width = Width; • } • public override double GetArea() • { • return Length*Width; • } • public double PerimeterIs() // 周长 • { • return (2*(Length+Width)); • } • }

  23. 【例4.5】 • // 派生类Square,从 Rectangular类中派生 • public class Square: Rectangular • { • public Square(string Color,double Side):base(Color,Side,Side) • {;} • } • public class TestInheritance • { • public static void Main() • { • Circle Cir= new Circle("orange",3.0); • Console.WriteLine("Circle color is {0},Circle area is {1}", Cir.GetColor(),Cir.GetArea()); • Rectangular Rect= new Rectangular("red",13.0, 2.0); • Console.WriteLine("Rectangualr color is {0},Rectangualr area is {1}, Rectangular perimeter is

  24. 【例4.5】 • {2}", Rect.GetColor(),Rect.GetArea(), Rect.PerimeterIs()); • Square Squ= new Square("green",5.0); • Console.WriteLine("Square color is {0},Square Area is {1}, Square perimeter is {2}", Squ.GetColor(),Squ.GetArea(), Squ.PerimeterIs()); • Shape Shp= Cir; • Console.WriteLine("Circle area is {0}", Shp.GetArea()); • Shp = Rect; • Console.WriteLine("Rectangualr area is {0}",Shp.GetArea()); • } • }

  25. 4.1.2多态 • 2. 抽象类与抽象方法 • 抽象类是一种特殊的基类,并不与具体的事物联系。抽象类的定义使用关键字abstract。在 • 图4.2 类的层次结构中,并没有“图形”这样具体事物,所以可以将“图形”定义为抽象类,派 • 生了“圆形”和“四边形”这样一些可以产生具体实例化的普通类。需要注意的是,抽象类是不 • 能被实例化,它只能作为其它类的基类。将Shape类定义为抽象类: • public abstract class Shape • { • … • } • 在抽象类中也可以使用关键字abstract定义抽象方法,要求所有的派生非抽象类都要重载实 • 现抽象方法。引入抽象方法的原因在于抽象类本身是一种抽象的概念,有的方法并不要具 • 体的实现,而是留下来让派生类来重载实现。Shape类中GetArea方法本身没什么具体的 • 意义,而只有到了派生类Circle类和Rectangular才可以计算具体的面积。 • 抽象方法写法: • public abstract double GetArea(); • 则派生类重载实现为: • public override double GetArea() • { • … • }

  26. 4.1.2多态 • 【例4.6】抽象类和抽象方法的实现 • using System; • //定义基类Shape • public abstract class Shape • { • protected string Color; • public Shape() • {;} • public Shape(string Color) • { • this.Color = Color; • } • public string GetColor() • { • return Color; • } • public abstract double GetArea(); • }

  27. 【例4.6】 • // 定义Circle类,从Shape类中派生 • public class Circle : Shape • { • private double Radius; • public Circle(string Color, double Radius) • { • this.Color = Color; • this.Radius = Radius; • } • public override double GetArea() • { • return System.Math.PI * Radius * Radius; • } • }

  28. 【例4.6】 • // 派生类Rectangular, 从Shape类中派生 • public class Rectangular:Shape • { • protected double Length, Width; • public Rectangular(string Color,double Length, double Width) • { • this.Color = Color; • this.Length = Length; • this.Width = Width; • } • public override double GetArea() • { • return Length*Width; • } • public double PerimeterIs() //周长 • { • return (2*(Length+Width)); • } • }

  29. 【例4.6】 • // 派生类Square, 从 Rectangular类中派生 • public class Square: Rectangular • { • public Square(string Color,double Side):base(Color,Side,Side) • {;} • } • public class TestInheritance • { • public static void Main() • { • Circle Cir= new Circle("orange",3.0); • Console.WriteLine("Circle color is {0},Circle area is {1}", Cir.GetColor(),Cir.GetArea()); • Rectangular Rect= new Rectangular("red",13.0, 2.0);

  30. 【例4.6】 • Console.WriteLine("Rectangualr color is {0},Rectangualr area is {1}, Rectangular perimeter is {2}", Rect.GetColor(),Rect.GetArea(), Rect.PerimeterIs()); • Square Squ= new Square("green",5.0); • Console.WriteLine("Square color is {0},Square Area is {1}, Square perimeter is {2}", Squ.GetColor(),Squ.GetArea(), Squ.PerimeterIs()); • } • }

  31. 4.1.2多态 • 3. 密封类和密封方法 • 抽象类是作为基类,不能被实例化,由其它类继承。相对应的还有一种不能被其它类继承 • 的类,叫密封类,使用sealed关键字定义。如果Rectangular类定义为密封类 : • public class rectangular:Shape • { • … • } • 这样Rectangular类的派生类Square就不再保留,否则,就会出错。 • 如果类的方法声明包含 sealed 修饰符,称该方法为密封方法。类的实例方法声明包含 • sealed 修饰符,则必须同时使用override修饰符。使用密封方法可以防止派生类进一步重 • 写该方法。如果将圆形Circle类的GetArea方法定义为密封类,必须先将Shape类GetArea • 方法定义为: • public virtual double GetArea() • { • … • } • 然后在Circle类中实现密封方法: • public sealed override double GetArea() • { • … • }

  32. 4.2 操作符重载 • 如果有一个复数Complex类对一元操作符“++”重载,可以写成: • public static Complex operator ++(Complex a) • { • … • } • 对二元操作符“+”可以写成: • public static Complex operator +(Complex a, Complex b) • { • … • }

  33. 4.2 操作符重载 • 一元操作符有一个参数,二元操作符有二个参数。重载操作符开始必须以public static修饰。可以重载的操作符包括: • 一元操作符:+ - ! ~ ++ -- true false • 二元操作符:+ - * / % & | ^ << >> == != > < >= <= • 下面的操作符要求同时重载,不能重载中间的单独一个: • 一元操作符:true和false • 二元操作符:== 和!=, >和<, >=和<= • 操作符重载给类的一些操作带来了方便。两个复数的实部相加运算写成: • public static double Add(complex a, complex b) • { • return a.r+b.r • } • 这样的写法不够简洁,并且类的成员修饰符不为public时就不能这样直接的操作。

  34. 4.2 操作符重载 • 【例4.7】操作符重载的实现 • using System; • class Complex • { • double r, v; //r+ v i • public Complex(double r, double v) • { • this.r=r; • this.v=v; • } • // 二元操作符”+”重载 • public static Complex operator +(Complex a, Complex b) • { • return new Complex(a.r+b.r, a.v+b.v); • }

  35. 【例4.7】 • // 一元操作符”-”重载 • public static Complex operator -(Complex a) • { • return new Complex(-a.r,-a.v); • } • // 一元操作符”++”重载 • public static Complex operator ++(Complex a) • { • double r=a.r+1; • double v=a.v+1; • return new Complex(r, v); • } • public void Print() • { • Console.Write(r+" + "+v+"i\n"); • } • }

  36. 【例4.7】 • class Test • { • public static void Main() • { • Complex a=new Complex(3,4); • Complex b=new Complex(5,6); • Complex c=-a; • c.Print(); • Complex d=a+b; • d.Print(); • a.Print(); • Complex e=a++; // 先赋值后++ • a.Print(); • e.Print(); • Complex f=++a; // 先++后赋值 • a.Print(); • f.Print(); • } • }

  37. 4.2 操作符重载 • 在操作符重载中,返回值往往需要“new”一个新的complex对象。 • 另外一种的操作符重载类型是用户定义的数据类型转换,它实现不同类型之间的转换,包括显式转换和隐式转换两种方式。 • 编程中往往需要将一个类型转换成另外一个类型。例如将int转换成double,它们是系统已经预定义的类型,编译器知道如何来执行它们的转换, 具体内容在下一节“类型转换”中讨论。如果它们中间有的类型不是编译器预定义的类型,编译器将不知道执行转换,解决的方法是使用用户定义的数据类型转换。 • 转换过程不会丢失数据而出现异常,就采用隐式转换。如果转换过程有可能丢失数据,就要采用显式转换。 • 隐式类型转换的写法如: • public static implicit operator Square(double s) • { • … • } • 实现double向Square转换功能。关键字explicit实现显式类型转换: • public static explicit operator double(Square s) • { • … • }

  38. 【例4.8】用户定义的数据类型转换。 • using System; • class Square • { • private double Side; • public Square(int s) • { • Console.WriteLine("int类型参数构造函数"); • Side=(double)s; • } • public Square(double s) • { • Console.WriteLine("double类型参数构造函数"); • Side=s; • } • // 重写object类的ToString()方法. • public override string ToString() • { • Console.WriteLine("重写object类的ToString()方法"); • return this.Side.ToString(); • }

  39. 【例4.8】 • // 重载”+” 操作符,参数为两个square类 • public static Square operator + (Square x,Square y) • { • Console.WriteLine("重载+操作符,参数为两个square类"); • return new Square(x.Side+y.Side); • } • // 重载”+”操作符,参数一个为square类,一个为double类型 • public static Square operator + (Square x,double y) • { • Console.WriteLine("重载+操作符,参数一个为square类,一个为double类型"); • return new Square(x.Side+y); • } • // 重载”+”操作符,参数一个为square类,一个为int类型 • public static Square operator + (Square x,int y) • { • Console.WriteLine("重载+操作符,参数一个为square类,一个为int类型"); • return x +(double)y; //调用上面的重载”+”操作符 • }

  40. 【例4.8】 • // 隐式类型转换,实现double类型转换为Square • public static implicit operator Square(double s) • { • Console.WriteLine("隐式类型转换,实现double类型转换为Square "); • return new Square(s); • } • // 隐式类型转换,实现int类型转换为Square • public static implicit operator Square(int s) • { • Console.WriteLine("隐式类型转换,实现int类型转换为Square "); • return new Square((double)s); • } • // 重载” == ”操作符 • public static bool operator ==(Square x,Square y) • { • Console.WriteLine("重载== 操作符,两个参数都为square类"); • return x.Side==y.Side; • }

  41. 【例4.8】 • // 重载” !=”操作符 • public static bool operator !=(Square x,Square y) • { • Console.WriteLine("重载!=操作符,两个参数都为square类"); • return !(x==y); //调用前面的重载”==”操作符 • } • // 当重载”==”和”!=”的同时还要重载object类的GetHashCode()和Equals(),否则编译器会出现警告 • // 也可以不重写这两个方法,对运行结果没有影响 • public override bool Equals(object o) • { • return this==(Square)o; • } • public override int GetHashCode() • { • return (int)Side; • }

  42. 【例4.8】 • // 重载” > ”操作符 • public static bool operator >(Square x,Square y) • { • Console.WriteLine("重载 >操作符,两个参数都为square类"); • return x.Side>y.Side; • } • // 重载” <”操作符 • public static bool operator <(Square x,Square y) • { • Console.WriteLine("重载<操作符,两个参数都为square类"); • return x.Side<y.Side; • } • // 重载” <= ”操作符 • public static bool operator <=(Square x,Square y) • { • Console.WriteLine("重载<=操作符,两个参数都为square类"); • return (x<y) || (x==y); //调用重载的操作符” ==”和”<” • }

  43. 【例4.8】 • // 重载” >=”操作符 • public static bool operator >=(Square x,Square y) • { • Console.WriteLine("重载>=操作符,两个参数都为square类"); • return (x>y) || (x==y); //调用重载的操作符” ==”和” >” • } • public static void Main() • { • Square s1=new Square(10); • Square s2=new Square(20); • Square s3=s1+s2; // 调用operator + (Square,Square) • Console.WriteLine(s3); // 调用重写object类的ToString()方法 • Console.WriteLine(s3+15); // 调用重写的operator + (Square,int)以及ToString() • Console.WriteLine(s3+1.5); // 调用重写的operator + (Square,double)和ToString() • s3=10; // 调用隐式转换public static implicit operator Square(int ) • Console.WriteLine(s3); • Square s4=10;

  44. 【例4.8】 • Console.WriteLine(s1==s4); // 调用== 操作符 • Console.WriteLine(s1!=s4); // 调用 != 操作符 • Console.WriteLine(s1>s2); // 调用 >操作符 • Console.WriteLine(s1<=s4); // 调用<=操作符 • } • } • 运行结果如图4.6所示。 • Square与double 和int 之间有两个隐式转换。从double以及int隐式转换过程 • 不会丢失数据而出现异常,所以采用了隐式转换。 • Square类默认的基类是Object类,所以可以重载Object类的方法ToString。 • WriteLine方法默认的参数为String对象,所以在输出之前都要调用ToString方 • 法,将参数转换为String类型。

  45. 【例4.8】 图4.6 运行结果

  46. 4.3 类型转换 • 实际编程中,经常用到类型的相互之间转换问题,如一个int类型要转换成一个long类型。类型转换方法分为隐式类型转换和显式类型转换,也可以采用Convert提供的方法实现类型转换。 • 4.3.1 隐式类型转换 • 隐式类型转换不需要加任何声明就可以实现的类型转换,规则简单。 • 1. 隐式数值转换 • 数值转换是指在整数类型、实数类型和字符类型之间的转换。sbyte类型向int类型转换是一种隐式数值类型转换,转换一般不会失败,也不会丢失数据。如: • sbyte a = 100; • int b = a; • 隐式数值类型转换如表4.1所示。 • 从int到long,long到float、double等几种类型转换时可能导致精度的下降,但不导致数量上的丢失。从表4.1中可以看出,任何的原始类型,如果值的范围完全包含在其它类型的值范围内,那么就能进行隐式转换。需要注意的是char类型可以转换为其它的整数或实数类型,但不存在其它类型转换为char类型。

  47. 1. 隐式数值转换 表4.1 隐式数值类型转换

  48. 1. 隐式数值转换 • 【例4.9】隐式数值转换。 • using System; • class ReferenceConversion • { • static void Main() • { • char a = 'm'; • int b = a; • Console.WriteLine("a equals:{0}",a); • Console.WriteLine("b equals:{0}",b); • } • } • 运行结果如下: • a equals:m • b equals:107 • 如果这样写: • int b = 7; • char a = b; • Console.WriteLine("a equals:{0}",a); • Console.WriteLine("b equals:{0}",b); • 编译器将报错:无法将类型“int”隐式转换为“char”。

  49. 4.3.1 隐式类型转换 • 2. 隐式枚举转换 • 隐式枚举转换只允许将十进制0转换为枚举类型的变量。 • 【例4.10】隐式枚举转换。 • using System; • enum Color • { • Red,Green,Blue • } • class EnumConversion • { • static void Main() • { • Color a = Color.Red; • Console.WriteLine("a equals:{0}",a); • a = 0; • Console.WriteLine("a equals:{0}",a); • } • } • 如果写a = 1或其它数值,编译器提示:无法将类型“int”隐式转换为“Color”。

  50. 4.3.1 隐式类型转换 • 3. 隐式引用转换 • 类型s向类型t隐式引用转换的条件是:s是从t派生来的,且s和t可以是接口或类。两个数组的之间的隐式转换的条件是:两个数组的维数相同,元素都是引用类型,且存在数组元素的隐式引用转换。例如: • class Employee // 隐含继承自System.Object • { • … • } • class App • { • Employee e; • object o = e; • … • } • 使用隐式转换的因为在于Employee是派生自Object类。

More Related