3. 第一章:C#面向对象编程之继承和多态

第一章:C#面向对象编程

第二节:继承和多态

继承可以让class具有一种特殊的能力,即实现class本身定义的所有功能外,还可以对父类(或称为基类、超类)的某些属性和功能进行扩展,这样的类我们称之为子类(或派生类)。

继承有如下的几个规则:

1. 可传递性:

如: C是B的子类,B是A的子类,那么C会同时继承B和A;(object为所有类的基类)

2. 唯扩展性:

子类应是对父类的扩展,而不能在子类除去父类里面的定义;

3. 构造函数和析构函数不能被继承:

除去构造函数和析构函数不能被继承,其他的成员都能被继承(注意区别:能被继承和能被访问,是两个概念)

4. 重载屏蔽性:

如果子类定义了和父类成员同名的新成员,那么会执行重载和覆盖逻辑。但要明白的是,这样做,并不是删除了父类的这些成员,而是不能再访问这些被重载和覆盖的成员而已。

5. 子类可以从父类的虚方法、虚属性以及虚索引器进行重载(即多态)

我们可以借用override关键字对父类的虚方法、虚属性以及虚索引器进行重载;

同时,我们也可以借用override关键字对抽象父类的抽象方法进行重载。

  abstract和virtural的区别:

    (1) abstract可以修饰class以及abstract class内部的函数、属性和索引器;而virtual不可以修饰class;

    (2) abstract修饰函数的时候,必须在abstract class才可以;而且abstract函数或属性不可以在abstract class里面有实现,但virtual必须要有实现。

    (3) virtual既可以修饰abstract class里面的函数、属性和索引器,也可以修饰一般class里面的函数、属性和索引器;

6. 子类只能继承一个父类(class),而可以继承多个接口(interface)(多重继承)

下图继承关系,可以让大家更好了解这些概念的意义:

具体的实现代码:

 1     public abstract class Creature
 2     {
 3         private string _spiece;
 4
 5         public Creature(string spiece)
 6         {
 7             this._spiece = spiece;
 8         }
 9
10         public string Spiece
11         {
12             get { return this._spiece; }
13         }
14
15         public abstract void Breath();
16     }
 1     public class Animal : Creature
 2     {
 3         private bool? _sex;
 4
 5         public Animal(string spiece)
 6             : base(spiece)
 7         {
 8             this._sex = null;
 9         }
10
11         public bool? Sex
12         {
13             get { return _sex; }
14         }
15
16         public virtual void Run()
17         {
18             Console.WriteLine("I am running...");
19         }
20
21         public override void Breath()
22         {
23             Console.WriteLine("I am breathing by animal respiration...");
24         }
25     }
 1     public class Monkey : Animal
 2     {
 3         public Monkey(string spiece)
 4             : base(spiece) { }
 5
 6         public void ClimbTree()
 7         {
 8             Console.WriteLine("I am climbing tree...");
 9         }
10
11         public override void Run()
12         {
13             Console.WriteLine("I am running with two legs, sometimes with four legs...");
14         }
15
16         public override void Breath()
17         {
18             Console.WriteLine("I am breathing with lung...");
19         }
20     }
 1     public class Fish : Animal
 2     {
 3         public Fish(string spiece)
 4             : base(spiece) { }
 5
 6         public override void Run()
 7         {
 8             Console.WriteLine("I am running in the water with fins...");
 9         }
10
11         public override void Breath()
12         {
13             Console.WriteLine("I am breathing with cheek...");
14         }
15     }
 1     public class Plant : Creature
 2     {
 3         public Plant(string spiece)
 4             : base(spiece) { }
 5
 6         public override void Breath()
 7         {
 8             Console.WriteLine("I am breathing by plant respiration...");
 9         }
10     }
 1     public class Tree : Plant
 2     {
 3         public Tree(string spiece)
 4             : base(spiece) { }
 5
 6         //重载Breath()内部调用base.Breath(),其实和不写没啥区别,这里只是想告诉大家本质是什么。
 7         public override void Breath()
 8         {
 9             base.Breath();
10         }
11     }

程序运行测试代码:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Creature creature001 = new Animal("Animal");
 6             Console.WriteLine(creature001.Spiece);
 7             creature001.Breath();
 8
 9             Console.WriteLine("—————————————————————————");
10
11             Creature creature002 = new Plant("Plant");
12             Console.WriteLine(creature002.Spiece);
13             creature002.Breath();
14
15             Console.WriteLine("—————————————————————————");
16
17             Animal animal001 = new Animal("Animal", true);
18             Console.WriteLine(animal001.Spiece);
19             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal001.Spiece, GetSexName(animal001.Sex)));
20             animal001.Breath();
21             animal001.Run();
22
23             Console.WriteLine("—————————————————————————");
24
25             Creature monkey001 = new Monkey("Monkey", true);
26             Console.WriteLine(monkey001.Spiece);
27             monkey001.Breath();
28
29             Console.WriteLine("—————————————————————————");
30
31             Animal animal002 = new Monkey("Monkey", false);
32             Console.WriteLine(animal002.Spiece);
33             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal002.Spiece, GetSexName(animal002.Sex)));
34             animal002.Breath();
35             animal002.Run();
36
37             Console.WriteLine("—————————————————————————");
38
39             Creature fish001 = new Fish("Fish", true);
40             Console.WriteLine(fish001.Spiece);
41             monkey001.Breath();
42
43             Console.WriteLine("—————————————————————————");
44
45             Animal fish002 = new Fish("Fish", true);
46             Console.WriteLine(fish001.Spiece);
47             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", fish002.Spiece, GetSexName(fish002.Sex)));
48             fish002.Breath();
49             fish002.Run();
50
51             Console.WriteLine("—————————————————————————");
52
53             Animal animal004 = new Monkey("Monkey", false);
54             Console.WriteLine(animal004.Spiece);
55             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", animal004.Spiece, GetSexName(animal004.Sex)));
56             animal002.Breath();
57             animal002.Run();
58
59             Console.WriteLine("—————————————————————————");
60
61             Monkey jack = new Monkey("Monkey", true);
62             Console.WriteLine(jack.Spiece);
63             Console.WriteLine(string.Format("Spiece:{0}; Sex:{1}", jack.Spiece, GetSexName(jack.Sex)));
64             jack.Breath();
65             jack.Run();
66             jack.ClimbTree();
67
68             Console.ReadLine();
69         }
70
71         private static string GetSexName(bool? value)
72         {
73             string sexName = null;
74             if (value == null)
75             {
76                 sexName = "undefined";
77             }
78             else
79             {
80                 sexName = value.Value ? "male" : "female";
81             }
82             return sexName;
83         }
84     }

运行结果:

Animal
I am breathing by animal respiration...
—————————————————————————
Plant
I am breathing by plant respiration...
—————————————————————————
Animal
Spiece:Animal; Sex:male
I am breathing by animal respiration...
I am running...
—————————————————————————
Monkey
I am breathing with lung...
—————————————————————————
Monkey
Spiece:Monkey; Sex:female
I am breathing with lung...
I am running with two legs, sometimes with four legs...
—————————————————————————
Fish
I am breathing with lung...
—————————————————————————
Fish
Spiece:Fish; Sex:male
I am breathing with cheek...
I am running in the water with fins...
—————————————————————————
Monkey
Spiece:Monkey; Sex:female
I am breathing with lung...
I am running with two legs, sometimes with four legs...
—————————————————————————
Monkey
Spiece:Monkey; Sex:male
I am breathing with lung...
I am running with two legs, sometimes with four legs...
I am climbing tree...

时间: 2024-08-02 20:49:06

3. 第一章:C#面向对象编程之继承和多态的相关文章

Java面向对象编程之继承(一)

前言 Java语言有三大重要的特性,分别是继承.多态和封装.今天我们就来聊聊继承,继承是复用程序代码的有力手段,使用继承我们会少写许多代码,也可以让我们在写代码的时候逻辑变得更加清楚. 继承的基本语法 在Java语言中,用"extends"关键字来表示一个类继承了另一个类,例如:  public class Sub extends Base{ ... } ,以上代码表明Sub类继承了Base类,我们说Sub类是Base类的子类,Base类是Sub类的父类. 那么Sub类到底继承了Bas

Scala 面向对象编程之继承

extends关键字 // Scala中,让子类继承父类,与Java一样,也是使用extends关键字 // 继承就代表,子类可以从父类继承父类的field和method:然后子类可以在自己内部放入父类所没有,子类特有的field和method:使用继承可以有效复用代码 // 子类可以覆盖父类的field和method:但是如果父类用final修饰,field和method用final修饰,则该类是无法被继承的,field和method是无法被覆盖的 class Person { private

Java面向对象编程之继承(二)

在上一篇博客中,我们已经了解继承的基本概念和语法,那么今天我们就来聊一聊有关于继承的其他东西. 让我们来了解一下什么是方法重载(overload)和方法覆盖(override) 方法重载(overload) 对于类的的方法(包括从父类中继承的方法),如果有两个方法的方法名相同,但参数不一致,那么可以说,一个方法是另一个方法的重载方法. 重载方法必须满足以下条件: 方法名相同 方法的参数类型.个数.顺序至少有一项不相同 方法的返回类型可以不相同 方法的修饰符可以不相同 其中,参数的类型.个数和顺序

js原生设计模式——2面向对象编程之继承—new类式继承

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>classInherit</title>    <script type="text/javascript">    //声明父类    function superClass(){        this.name

js原生设计模式——2面向对象编程之继承—call(this)构造函数式继承

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>constructorfunctionInherit</title>    <script type="text/javascript">    //声明父类    function superClass(id){  

7、JS面向对象编程之继承

Javascript本身是从Perl语言的语法演变而来的,本质上是脚本语言,随着版本的更新逐渐加入的对面向对象的模拟.我认为Js的面向对象模拟总体上做得还是不错的,因为我们不能盲从任何一种理念,不能纯粹的为了OOP而OOP,我们需要抓住的是面向对象的好处到底是什么?为了这些优点去OOP,才是最明智的选择,所以说Js做得还不错. Js的继承在很多书里面细致的分了很多种类型和实现方式,大体上就是两种:对象冒充.原型方式.这两种方式各有优点和缺陷,这里我先列举出来,再从底层分析区别: (一)对象冒充

C++面向对象编程之继承

一. 封装和继承 1.1 封装的概念 封装:通过访问控制属性对类类型中的属性和行为进行打包和限制. 1.2 继承:通过一种机制表达出类型之间的共性和特性的方式. 继承基本语法: class 子类名 : 继承方式1 父类1,继承方式2 父类2... { 类的定义 }; 继承方式: public  公有方式 private 私有方式 protected 保护方式 1.3 继承的特性 (1) 一个子类类型的对象在任何时候都可以看作基类类型的对象(心里始终要记着). (2) 一个父类类型的对象作为子类对

JS面向对象编程之:封装、继承、多态

最近在实习公司写代码,被隔壁的哥们吐槽说,代码写的没有一点艺术.为了让我的代码多点艺术,我就重新温故了<javascript高级程序设计>(其中几章),然后又看了<javascript设计模式>,然后觉得要写点心得体会,来整理自己所学的吧.以下是我个人见解,错了请轻喷,欢迎指出错误,乐于改正. 一.封装 (1)封装通俗的说,就是我有一些秘密不想让人知道,就通过私有化变量和私有化方法,这样外界就访问不到了.然后如果你有一些很想让大家知道的东西,你就可以通过this创建的属性看作是对象

深入理解JavaScript系列(17):面向对象编程之概论

介绍 在本篇文章,我们考虑在ECMAScript中的面向对象编程的各个方面(虽然以前在许多文章中已经讨论过这个话题).我们将更多地从理论方面看这些问题. 特别是,我们会考虑对象的创建算法,对象(包括基本关系 - 继承)之间的关系是如何,也可以在讨论中使用(我希望将消除之前对于JavaScript中OOP的一些概念歧义). 英文原文:http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/ 概论.范式与思想 在进行E