- C# 多态性

多态是同一个行为具有多个不同表现形式或形态的能力。

多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为”一个接口,多个功能”。

多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。

在 C# 中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自 Object。

多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:

现实中,比如我们按下 F1 键这个动作:

  • 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;

  • 如果当前在 Word 下弹出的就是 Word 帮助;

  • 在 Windows 下弹出的就是 Windows 帮助和支持。
    同一个事件发生在不同的对象上会产生不同的结果。

- 静态多态性

在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:

  • 函数重载

  • 运算符重载

  • 运算符重载将在下一章节讨论,接下来我们将讨论函数重载。

- 函数重载

您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。

下面的实例演示了几个相同的函数 Add(),用于对不同个数参数进行相加处理:

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
namespace PolymorphismApplication
{
public class TestData
{
public int Add(int a, int b, int c)
{
return a + b + c;
}
public int Add(int a, int b)
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
TestData dataClass = new TestData();
int add1 = dataClass.Add(1, 2);
int add2 = dataClass.Add(1, 2, 3);

Console.WriteLine("add1 :" + add1);
Console.WriteLine("add2 :" + add2);
}
}
}

下面的实例演示了几个相同的函数 print(),用于打印不同的数据类型:

阅读全文 »

又到了周末,虽然天气炎热,但钓鱼人的热情并没有被打消。上个周末去钓大鲤鱼的计划没能实现,我总结了一周,觉得主要原因是没有打窝。所以今天特意带了红虫颗粒和谷麦窝,准备在新的钓位上再次尝试。

9点到达水库边,太阳早早地出来了。为了防晒,我选择了一个背靠大树的钓位,面对着水库。钓位的左侧是一个小湾子,形状像一个字母“C”,岸边都是树。本来这个湾子是个很好的钓位,但水质不好,垃圾也很多,连浮漂都站不起来。所以我选了一个稍微往外一点的位置。不多废话,选好钓位后,我先打窝。在3.6米的位置,我打了几把红虫颗粒,准备钓小鲫鱼。在6.3米的位置,我用长竿挂上玉米,准备钓大鲤鱼。

一番准备之后,已经是9点半了。我决定先用12尺的玄武人Y钓一些小鱼回去喂乌龟。撮了两个大饵,抛入水中先找底。结果浮漂一入水就全没入水中,一提竿大弯弓水下没动静,感觉像挂底,习惯性的拿着鱼竿向上轻弹两下,突然一股具大的力道从鱼竿传到手撑,鱼竿差点脱手而去,鱼线带着嗖嗖嗖的声音往外串,,我急忙调整鱼竿的角度,左右晃动鱼竿,希望能让鱼竿弯起来。但感觉就像是牵了一头不听指挥的牛,一直往前冲。结果鱼脱钩了,4号袖钩都被拉直了。看着水面上翻起的夹着浑水的大水花,我的内心久久不能平静。过了几分钟,等我心情平复了一些,我分析了一下原因。这其实是跑鱼的正常现象。12尺的玄武人Y有点短,主线0.8号,子线0.4号,加上4号袖钩,这样的配置确实只适合钓小鱼。再加上水深只有60厘米,很难有鱼游动的空间。一想到这些,我不再那么懊恼了。钓鱼玩的就是一个过程,于是我收拾好心情,继续钓。

刚刚跑了鱼,窝里肯定已经没有鱼了。于是我准备去玩路亚。上次的路亚装备还在,我准备玩飞蝇。出人意料的是,路亚鱼口很好,还解锁了鲈鱼。

路亚上的第一条鲈鱼

用2克小亮片上的第一条鲈鱼,咬口猛,中鱼瞬间有时会跳出水面洗腮

阅读全文 »

又到了令人开心和愉快的周末时光!原本计划这个周末去河边玩路亚微物钓鱼,不过上周下了几天雨,导致河水暴涨,无法安全地玩耍。为了保证安全,我决定改去三一水库钓小鱼,毕竟水库的深度只有大约1.5米,环境也很舒适。

钓位环境

我准备了一根6.3米长的钓竿,上面挂玉米,打算用来钓鲤鱼;另外还有一根3.6米短竿,用来钓小鲫鱼。

阅读全文 »

- 【Hexo】GitHub博客多项目重定向配置多个顶级域名

闲来无事用博客名新注册了一个域名:www.bytefisher.top 刚开通博客的时候随便注册了一个: www.ai-fish.top 想着新域名和博客名称一致要好记一些,但是也不想直接替换原来的域名,毕竟花了钱买的,不能浪费。就想着给博客同时绑定两个顶级域名,然而GitHub Pages 只支持一个自定义域名,为了要兼容旧域名的访问,在网上一翻搜索查找,还真找到了一些方案:

  • 301重定向

  • 服务器重定向

  • GitHub多项目重定向

  • 域名注册商重定向

大概看了一下,对于向我这种新手小白,还是觉得GitHub多项目重定向这一方案要简单一些。那就先折腾简单的吧,另外几种方案有机会再尝试。

- 建立中转仓库

需要在 GitHub 上再新建一个仓库,用来中转旧域名 www.ai-fish.top 中的访问到新的域名 www.bytefisher.top 中转仓库里面不会有过多内容。创建它只是为了存放 CNAME 文件 和 404.html文件,告诉 GitHub Pages 我们有两个域名而已。我创建了一个名为ByteFisher的仓库,正常情况下,访问这个仓库 GitHub Pages 的域名前缀为 用户名.github.io/ByteFisher
图1 创建中转仓库 ByteFisher

- 添加 GitHub Pages 服务

图2 中转仓库CNAME文件中填写旧的域名 :www.ai-fish.top

图3 修改博客主仓库中CNAME文件,填写新的域名:www.bytefisher.top

阅读全文 »

- C# 继承

继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。

当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类。

继承的思想实现了 属于(IS-A) 关系。例如,哺乳动物 属于(IS-A) 动物,狗 属于(IS-A) 哺乳动物,因此狗 属于(IS-A) 动物。

- 基类和派生类

一个类可以派生自多个类或接口,这意味着它可以从多个基类或接口继承数据和函数。

C# 中创建派生类的语法如下:

1
2
3
4
5
6
7
8
<访问修饰符> class <基类>
{
...
}
class <派生类> : <基类>
{
...
}

假设,有一个基类 Shape,它的派生类是 Rectangle:

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;
namespace InheritanceApplication
{
class Shape
{
public void setWidth(int w)
{
width = w;
}
public void setHeight(int h)
{
height = h;
}
protected int width;
protected int height;
}

// 派生类
class Rectangle: Shape
{
public int getArea()
{
return (width * height);
}
}

class RectangleTester
{
static void Main(string[] args)
{
Rectangle Rect = new Rectangle();

Rect.setWidth(5);
Rect.setHeight(7);

// 打印对象的面积
Console.WriteLine("总面积: {0}", Rect.getArea());
Console.ReadKey();
}
}
}

当上面的代码被编译和执行时,它会产生下列结果:

总面积: 35

- 基类的初始化

派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。您可以在成员初始化列表中进行父类的初始化。

下面的程序演示了这点:

阅读全文 »

- C# 类(Class)

当你定义一个类时,你定义了一个数据类型的蓝图。这实际上并没有定义任何的数据,但它定义了类的名称意味着什么,也就是说,类的对象由什么组成及在这个对象上可执行什么操作。对象是类的实例。构成类的方法和变量称为类的成员。

- 类的定义

类的定义是以关键字 class 开始,后跟类的名称。类的主体,包含在一对花括号内。下面是类定义的一般形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<access specifier> class  class_name
{
// member variables
<access specifier> <data type> variable1;
<access specifier> <data type> variable2;
...
<access specifier> <data type> variableN;
// member methods
<access specifier> <return type> method1(parameter_list)
{
// method body
}
<access specifier> <return type> method2(parameter_list)
{
// method body
}
...
<access specifier> <return type> methodN(parameter_list)
{
// method body
}
}

请注意:

  • 访问标识符 指定了对类及其成员的访问规则。如果没有指定,则使用默认的访问标识符。类的默认访问标识符是 internal,成员的默认访问标识符是 private。

  • 数据类型 指定了变量的类型,返回类型 指定了返回的方法返回的数据类型。

  • 如果要访问类的成员,你要使用点(.)运算符。

  • 点运算符链接了对象的名称和成员的名称。

下面的实例说明了目前为止所讨论的概念:

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
namespace BoxApplication
{
class Box
{
public double length; // 长度
public double breadth; // 宽度
public double height; // 高度
}
class Boxtester
{
static void Main(string[] args)
{
Box Box1 = new Box(); // 声明 Box1,类型为 Box
Box Box2 = new Box(); // 声明 Box2,类型为 Box
double volume = 0.0; // 体积

// Box1 详述
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;

// Box2 详述
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;

// Box1 的体积
volume = Box1.height * Box1.length * Box1.breadth;
Console.WriteLine("Box1 的体积: {0}", volume);

// Box2 的体积
volume = Box2.height * Box2.length * Box2.breadth;
Console.WriteLine("Box2 的体积: {0}", volume);
Console.ReadKey();
}
}
}
阅读全文 »