在 C# 里面,接口的定义只需要类里面存在和接口声明相同的方法或属性就可以,而存在的方法或属性是在子类定义的还是基类里面定义的都无所谓。也就是在基类里面写好了方法,但不继承接口,等子类继承接口的时候就不需要子类实现方法。通过这样的方法可以在基类里面添加一些辅助方法,而这些方法默认不给子类开启,除非子类继承了接口

在基类定义的方法,如果在子类继承的接口里面声明的方法刚好和基类定义的相同,那么子类可以不需要再次定义。在基类可以判断当前自己的类型是否继承了接口

这个方法用在基类里面期望在特定的代码里面给子类暴露一些内部的方法,但是又不能让子类随意调用。或者预设了一些方法,这些方法存在性能或其他的问题,只有子类声明自己需要这个功能的时候才被调用

内部方法隐藏

在基类里面有一些内部的方法,默认不让子类使用的,但只有某些特殊的子类的情况才能被使用。同时这些内部方法还可能被外部的其他方法调用,不一定是子类

按照以上的约定就可以写出如下代码

    public interface ILindexiDb
{
string GetPrivateString();
} public class BassClass
{
public string GetPrivateString()
{
if (!(this is ILindexiDb))
{
throw new NotSupportedException("这个方法除非是林德熙逗比才能使用,其他人不能使用");
} return "林德熙是逗比";
}
}

从代码可以看到,除非这个类继承了 ILindexiDb 不然 GetPrivateString 方法将会异常,因为我期望这个方法只有我才能调用

那么假如我有一个 Foo 的接口里面就需要使用到对应的方法,而默认业务想要返回的方法是基类定义的上面的方法

    public interface IFoo
{
void GetString();
}

不明真相的小伙伴可能会如何写?

    public class Foo : BassClass, IFoo
{
public void GetString()
{
Console.WriteLine(GetPrivateString());
}
}

上面代码是小伙伴会直接写出的代码,然而这段代码没有运行的时候就会炸,原因是在基类判断当前这个类没有继承林德熙是逗比这个接口

在我将基类放在一个程序集编译为dll之后,小伙伴没有方法直接看到源代码,他在调用 GetPrivateString 方法的时候抛出了方法没有支持异常,于是小伙伴会认为这个方法还没实现,她就不会想要去使用这个方法

而林德熙逗比将会写出下面代码用来访问内部的方法

    public class Foo2 : BassClass, ILindexiDb, IFoo
{
public void GetString()
{
Console.WriteLine(GetPrivateString());
}
}

因为注入的都是 IFoo 接口,小伙伴都不知道实际实现的 Foo2 里面做了什么,如果不信,请在 VisualStudio 里面用上代码,然后调试一下。此时很难知道 Foo2 里面做了什么魔法让调用 GetPrivateString 方法不会异常,因为在调试的时候是很难知道当前这个类继承了哪些接口,而一般调试的时候都不会注意到某个类继承的接口会影响到具体调用的方法

我写了很多调试的方法,请看dotnet 代码调试方法

引用子类方法

按照这个约定,其实还可以让基类在满足一定条件的时候才能执行,这个条件需要子类定义。这个方法是上面说到的内部方法隐藏的升级,用起来将会更复杂

在基类里面判断当前类是否继承了某个接口,如果继承了,那么将会可以调用接口的方法。这个方法一般用在某个接口的声明要用到很多基类的信息才能实现,或某个接口本身不适合在外部的其他类继承,只能由子类继承

例如我定义了接口,用来判断林德熙是不是逗比的接口,而这个接口的方法实现需要依赖于基类的内容才能判断,但基类的内容是私有的,从业务上也不应该让外部方法知道

    public interface ILindexiConverter
{
bool CheckLindexiIsDoubi();
}

以下是基类的定义

    public class BassClass
{
protected string Name { get; } = "林德熙逗比"; public string GetPrivateString()
{
// 忽略代码
}
}

基类里面定义的 Name 属性是不能给外部类知道的,要不大家都知道我逗比,只有子类才能知道

此时基类需要依赖 ILindexiConverter 的判断才能决定是否需要做业务

        public string GetPrivateString()
{
// 忽略代码 if (!lindexiConverter.CheckLindexiIsDoubi())
{
throw new NotSupportedException("这个方法除非是林德熙逗比才能使用,其他人不能使用");
} }

然而 ILindexiConverter 接口除非是子类,其他类是无法按照预期做到的,于是在基类里面可以这样写

            if (this is ILindexiConverter lindexiConverter)
{
if (!lindexiConverter.CheckLindexiIsDoubi())
{
throw new NotSupportedException("这个方法除非是林德熙逗比才能使用,其他人不能使用");
}
}

判断当前这个类是否有继承 ILindexiConverter 接口,如果有就调用方法,按照这个方式写小伙伴就更加不能简单调用这个方法

而作为逗比我将会写出下面的代码,用于调用

    public class Foo2 : BassClass, ILindexiDb, IFoo, ILindexiConverter
{
public void GetString()
{
Console.WriteLine(GetPrivateString());
} /// <inheritdoc />
public bool CheckLindexiIsDoubi()
{
return base.Name == "林德熙逗比";
}
}

我在 Foo2 里面的 CheckLindexiIsDoubi 用到基类的属性判断,同时基类因为子类继承了预期接口而能使用

这就是通过在基类里面定义好方法和定义好代码逻辑,只要子类继承接口才能实现

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

C# 在基类定义好方法让子类继承接口就能实现的更多相关文章

  1. 2019-7-29-C#-在基类定义好方法让子类继承接口就能实现

    title author date CreateTime categories C# 在基类定义好方法让子类继承接口就能实现 lindexi 2019-07-29 09:57:49 +0800 201 ...

  2. C#中通过类来继承两个接口,父类实例化接口中的方法,子类继承父类,调用方法

    实现了父类继承接口,父类实例化接口的方法,子类继承父类,子类调用父类的方法直接使用 代码如下: using System; using System.Collections.Generic; usin ...

  3. Kendo UI - Class 基类定义

    在 kendo 中,使用原型继承机制,Class 是 Kendo 中的基类,定义了函数 extend 用来派生其它类. function Class() {} Class.extend = funct ...

  4. 派生类地址比基类地址少4(子类与基类指针强行转换的时候,值居然会发生变化,不知道Delphi BCB是不是也这样) good

    大家对虚表并不陌生,都知道每个含有虚函数的类对象都有1个虚指针,但是在现实使用中,却总是因为这而调试半天,才发现原来是虚指针惹的祸.我这几天在调试代码时候也中招了,我的问题是这样的,如下图,CTree ...

  5. C++//菱形继承 //俩个派生类继承同一个基类 //又有某个类同时继承俩个派生类 //成为 菱形继承 或者 钻石 继承//+解决

    1 //菱形继承 2 //俩个派生类继承同一个基类 3 //又有某个类同时继承俩个派生类 4 //成为 菱形继承 或者 钻石 继承 5 6 #include <iostream> 7 #i ...

  6. .NET Framework中Object基类有哪些方法?

    ToString(),虚方法,任何子类可重写自定义 GetType(),非虚,返回类型名 Equals(),虚方法,默认情况下判定两个引用是否指向同一实例.(ReferenceEquals()功能相同 ...

  7. Java Swing类 例子代码:将子类继承JFrame 并且接口按键监听ActionLisetener (将内容直接添加到JFrame不创建Contaniner)

    package rom; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import ...

  8. 流畅python学习笔记:第十一章:抽象基类

    __getitem__实现可迭代对象.要将一个对象变成一个可迭代的对象,通常都要实现__iter__.但是如果没有__iter__的话,实现了__getitem__也可以实现迭代.我们还是用第一章扑克 ...

  9. 流畅的python学习笔记:第十一章:抽象基类

    __getitem__实现可迭代对象.要将一个对象变成一个可迭代的对象,通常都要实现__iter__.但是如果没有__iter__的话,实现了__getitem__也可以实现迭代.我们还是用第一章扑克 ...

随机推荐

  1. Sublime text2 常用插件

    很早就安装了这款软件,因为听说很NB.但是一直都是习惯用vim, 所以一直没有去学习它, 现在用用感觉确实很不错,所以找了些插件, 参考网址: http://www.hphq.net/Marketin ...

  2. java 使用 POI 操作 XWPFDocumen 创建和读取 Office Word 文档基础篇

    注:有不正确的地方还望大神能够指出,抱拳了 老铁! 参考 API:http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDoc ...

  3. 2019.10.17beta

    import socket import subprocess import os server = socket.socket() server.bind( ('127.0.0.1',8888) ) ...

  4. hadoop生态系统默认port集合

    版权声明:本文为博主John Lau原创文章.未经博主同意不得转载 https://blog.csdn.net/GreatElite/article/details/24651569      1 H ...

  5. iOS viewDidLayoutSubviews,viewdidload

    由于种种原因,最近才开始真正在新项目中使用autolayout,使用过程中虽说是比较顺畅,但是也遇到了一些麻烦,比如: 我使用的XIB默认是4寸屏幕,我再XIB中增加一个viewA,宽度为320,约束 ...

  6. Vue组件跨层级通信

    正常组件间通信 父->子组件 是通过属性传递 子->父组件 是通过this.$emit()传递 this.$emit()返回的是this,如果需要一些值 可使用callback方式传递 p ...

  7. 在JS中模拟表单的post提交,进行页面的跳转

    原文链接:https://blog.csdn.net/jal517486222/article/details/83147761 /* *功能: 模拟form表单的提交 *参数: URL 跳转地址 P ...

  8. Resharper 如何把类里的类移动到其他文件

    有时候,看到一个类里有很多类,需要把他移动其他文件 假如有一个类 class A { class B { } } 如何把 B 移动文件 B里? 一般使用 快捷键是 Resharper 的快捷键,如果不 ...

  9. uni-app设置 video开始播放进入全屏状态

    有一video标签 <video id="myVideo" :src="videoUrl"></video> 获取 video 上下文 ...

  10. 从外网站点获取的html去除换行回车制表位\n\r\t

    StringStr.Replace("\\r", "").Replace("\\n", "").Replace(&quo ...