大多数人,都低估了编程学习的难度,而高估了自己的学习能力和毅力。
当前系列: C#语法 修改讲义

复习:J&C:面向对象:继承(构造函数调用 & 禁止) / 现代接口 

继承

不同的关键字

  • sealed:对应Java的final,标记某个类不能再被继承,比如
    sealed class Student : Person {}
    此外,静态类不能被继承。
  • base:对应Java的super,调用构造函数方式使用冒号(:)
    public OnlineStudent() : base("atai")
    {
  • protected internal,protected和internal之间是一种“或”的关系,即:
    • 标记了protected internal的类成员,既可以在当前项目中使用
    • 也可以在子类中使用

as

复习:is(Java中的instanceof

C#中还利用直接使用as进行转换。如果转换不成功,会返回null值。

Student wx = new OnlineStudent
{
    City = "西安"
};

OnlineStudent owx = wx as OnlineStudent;
if (owx == null)  //转换没成功

as在底层实际上是也利用了is,但飞哥个人认为as的写法更“舒服”一点。同学们可以依据自己的喜好选择使用is或as。


new的隐藏

关于多态,之前我们学习的是C#中可以使用virtual关键字定义虚方法,然后在子类中override:这样,调用方法的依据是对象而不是变量类型。

但是,#试一试#没有virtual和override,会得到一个警告,大意是:

子类Student的Eat()方法会隐藏(hide)父类Person的Eat()方法。如果这是我们有意而为之的(intented),让我们添加new关键字。

所以,规范的写法应该是:

public class Student
{
    internal void Eat()

class OnlineStudent : Student
{
    internal new void Eat()   //注意关键字new

这样的话,变量调用的方法就不再根据对象而是根据变量类型了:

//OnlineStudent wx = new OnlineStudent();
Student wx = new OnlineStudent();

wx.Eat();  //哪一个Eat()方法?

new还可以作用于静态方法。


接口显式实现

之前我们学习的,在C#中都被称为接口的隐式实现

但假如一个子类实现了多个接口,且多个接口中定义了相同方法的时候,按隐式实现如何区分呢?C#中引入了接口的显式实现。

比如我们两个接口,都定义了Practise()方法:

internal interface IPlay
{
    void Practise();
}

internal interface ILearn
{
    void Practise();
}

现在就不能在Student中隐式实现Practise()了,因为子类中只能声明一个Practise()方法啊!

所以我们需要进行区分:

void IPlay.Practise()  //不能有访问修饰符
{
    Console.WriteLine("玩");
}

void ILearn.Practise()  //接口名前缀
{
    Console.WriteLine("学习");
}

这样就OK了,但是还要注意一点,显式实现的接口方法,能用子类类型的变量进行调用,而是:

IPlay atai = new Student();
atai.Practise();

ILearn xj = new Student();
xj.Practise();


扩展方法

引入了extension method,其特点为:

  1. 在原有类(如IEnumerable<int>)之外另外声明一个类(如:Enumerable,以下简称“扩展类”),扩展类必须是静态(static)的,类名其实并不重要(不会被用到)
  2. 在扩展类中声明static方法
    • 方法的第一个参数必须带 this 关键字,且
    • 后跟一个原有类类型的参数(通常命名为source)
  3. 于是可以直接用扩展类实例调用这个方法,调用时应忽略第一个this参数
  4. 扩展方法仅在扩展类没有相应的实例方法时才会被调用。即:如果扩展类中本身就有一个和扩展方法签名相同的方法,会直接调用实例方法而不是扩展方法

我们也可以自定义自己的扩展方法:

namespace MyNamespace
{
    public static class TeacherExtesion /*毫无意义的XXXX也行,^_^*/
    {
        public static void Greet(this Teacher teacher, string words)
        {
            //teacher参数是可以作为正常参数使用的
            Console.WriteLine($"我是{teacher.Name},{words}");
        }

        //方法重载
        public static void Greet(this Teacher teacher)
        {

        }
    }
}


作业

  1. 在DLinkExtension类上声明一个扩展方法GetMax()方法,可以用双向链表对象调用,找到链表中最大值。

其他见:J&C:面向对象:继承(构造函数调用 & 禁止) / 现代接口(可利用显式接口,实现完成第7题)

学习笔记
源栈学历
今天学习不努力,明天努力找工作

作业

觉得很 ,不要忘记分享哟!

任何问题,都可以直接加 QQ群:273534701

在当前系列 C#语法 中继续学习:

多快好省!前端后端,线上线下,名师精讲

  • 先学习,后付费;
  • 不满意,不要钱。
  • 编程培训班,我就选源栈

更多了解 加:

QQ群:273534701

答疑解惑,远程debug……

B站 源栈-小九 的直播间

写代码要保持微笑 (๑•̀ㅂ•́)و✧

公众号:源栈一起帮

二维码