C#学习笔记(二):继承、接口和抽象类

继承

密封类

密封类(关键字sealed)是不允许其它类继承的,类似Java中的final关键字。

1 public sealed class SealedClassName
2 {
3     //...
4 }

初始化顺序

子类初始化顺序如下:

  1. 初始化类的实例字段;
  2. 调用基类的构造函数;
  3. 调用子类的构造函数。
 1 using System;
 2 
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             new C();
10 
11             Console.ReadKey();
12         }
13     }
14 
15     public class A
16     {
17         public A()
18         {
19             Console.WriteLine("A 类构造函数被调用。");
20         }
21     }
22 
23     public class B : A
24     {
25         public B()
26         {
27             Console.WriteLine("B 类构造函数被调用。");
28         }
29     }
30 
31     public class C : B
32     {
33         public C()
34         {
35             Console.WriteLine("C 类构造函数被调用。");
36         }
37     }
38 }

结果如下:

1 A 类构造函数被调用。
2 B 类构造函数被调用。
3 C 类构造函数被调用。

带参数的构造函数

Java中使用super调用父类的构造函数,而C#中则使用base,同时写法也稍微有点不同,如下:

 1 using System;
 2 
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             new C();
10 
11             Console.ReadKey();
12         }
13     }
14 
15     public class A
16     {
17         public A(int a, int b)
18         {
19             Console.WriteLine("A 类构造函数被调用。");
20             Console.WriteLine(a + ":" + b);
21         }
22     }
23 
24     public class B : A
25     {
26         public B(int name1, int name2) : base(name1, name2)
27         {
28             Console.WriteLine("B 类构造函数被调用。");
29         }
30     }
31 
32     public class C : B
33     {
34         public C() : base(50, 100)
35         {
36             Console.WriteLine("C 类构造函数被调用。");
37         }
38     }
39 }

输出如下:

1 A 类构造函数被调用。
2 50:100
3 B 类构造函数被调用。
4 C 类构造函数被调用。

方法多态

子类重写父类的方法使用virtual和override实现。

 1 using System;
 2 
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             new C().func();
10 
11             Console.ReadKey();
12         }
13     }
14 
15     public class A
16     {
17         public virtual void func()
18         {
19             Console.WriteLine("A 类的 func 方法调用。");
20         }
21     }
22 
23     public class B : A
24     {
25         public override void func()
26         {
27             Console.WriteLine("B 类的 func 方法调用。");
28         }
29     }
30 
31     public class C : B
32     {
33         public override void func()
34         {
35             base.func();
36             Console.WriteLine("C 类的 func 方法调用。");
37         }
38     }
39 }

输出如下:

1 B 类的 func 方法调用。
2 C 类的 func 方法调用。

阻止重写方法

如果不希望虚方法被重写,可以使用sealed关键字。

1 public sealed override void func()
2 {
3     //...
4 }

新成员方法隐藏老成员方法

使用new关键字可以隐藏非虚的老成员方法。

 1 using System;
 2 
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             C c = new C();
10             c.func();
11             ((B)c).func();
12             ((A)c).func();
13 
14             Console.ReadKey();
15         }
16     }
17 
18     public class A
19     {
20         public void func()
21         {
22             Console.WriteLine("A 类的 func 方法调用。");
23         }
24     }
25 
26     public class B : A
27     {
28         public new void func()
29         {
30             Console.WriteLine("B 类的 func 方法调用。");
31         }
32     }
33 
34     public class C : B
35     {
36         public new void func()
37         {
38             Console.WriteLine("C 类的 func 方法调用。");
39         }
40     }
41 }

输出如下:

1 C 类的 func 方法调用。
2 B 类的 func 方法调用。
3 A 类的 func 方法调用。

接口

C#中不允许多重继承,但接口可以多重继承。

接口声明

声明一个接口的写法如下:

1 public interface ICustom
2 {
3 }

C#中接口规则:

  1. 定义的方法不需要添加public等限定符,默认的所有方法都是public的;
  2. 可以包含方法、属性、事件和索引器;
  3. 不可以包含字段、运算符重载、构造函数和析构函数;
  4. 也不可以包含静态相关的所有定义;

类实现接口

实现接口的写法与继承一致:

 1 using System;
 2 
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             ICustom custom = new Custom();
10             custom.name = "A";
11             custom.MoveTo(200, 100);
12 
13             Console.ReadKey();
14         }
15     }
16 
17     public interface ICustom
18     {
19         string name { set; get; }
20 
21         void MoveTo(float x, float y);
22     }
23 
24     public class Custom : ICustom
25     {
26         public string name { get; set; }
27 
28         public void MoveTo(float x, float y)
29         {
30             Console.WriteLine("Custom "" + name + "" move to: " + x + ", " + y);
31         }
32     }
33 }

输出如下:

Custom "A" move to: 200, 100

接口的隐式实现和显式实现

如果在实现接口时没有指明该方法是属于哪个接口的话,称为隐式实现,如上面的例子。如果指明了方法是来自哪个接口则称为显式实现。

C#中的隐式实现与Java和AS3的使用一致,就不多讲,下面主要说一下接口的显式实现。

 1 using System;
 2 
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             Custom custom = new Custom();
10             custom.name = "A";
11             (custom as ICustomA).MoveTo(200, 100);
12             (custom as ICustomB).MoveTo(200, 100);
13 
14             Console.ReadKey();
15         }
16     }
17 
18     public interface ICustomA
19     {
20         string name { set; get; }
21 
22         void MoveTo(float x, float y);
23     }
24 
25     public interface ICustomB
26     {
27         string name { set; get; }
28 
29         void MoveTo(float x, float y);
30     }
31 
32     public class Custom : ICustomA, ICustomB
33     {
34         public string name { get; set; }
35 
36         void ICustomA.MoveTo(float x, float y)
37         {
38             Console.WriteLine("ICustomA "" + name + "" move to: " + x + ", " + y);
39         }
40 
41         void ICustomB.MoveTo(float x, float y)
42         {
43             Console.WriteLine("ICustomB "" + name + "" move to: " + x + ", " + y);
44         }
45     }
46 }

运行结果如下:

1 ICustomA "A" move to: 200, 100
2 ICustomB "A" move to: 200, 100

显示接口总结:

  1. 显示接口一般用于多个接口实现时,存在同名方法但需要不同的处理时。
  2. 我们发现如果使用显示的接口,需要将对象转换为对应的接口对象才能调用到对应的接口方法。
  3. 显示实现接口时不能写public在前方。
  4. 显示实现的接口不能由类直接访问,必须转换为对应的接口对象才行。

抽象类

C#中,抽象类使用与Java中一致,我们写一个例子来验证即可。

 1 using System;
 2 
 3 namespace Study
 4 {
 5     class Program
 6     {
 7         static void Main(string[] args)
 8         {
 9             Custom custom = new Custom();
10             custom.name = "A";
11             custom.MoveTo(200, 100);
12 
13             Console.ReadKey();
14         }
15     }
16 
17     public abstract class AbstractCustom
18     {
19         public string name { set; get; }
20 
21         public abstract void MoveTo(float x, float y);
22     }
23 
24     public class Custom : AbstractCustom
25     {
26         public override void MoveTo(float x, float y)
27         {
28             Console.WriteLine("Custom "" + name + "" move to: " + x + ", " + y);
29         }
30     }
31 }

运行结果如下:

Custom "A" move to: 200, 100

抽象类总结:

  1. 抽象类也是类,所以不能多重继承;
  2. 抽象类不能实例化,可以包含抽象方法,抽象方法不能实现;
  3. 抽象方法为虚方法;
  4. 非抽象子类必须实现抽象方法;
原文地址:https://www.cnblogs.com/hammerc/p/4598432.html