From 471d47441e7cc22dcc096aaddc2d13bf07772fc0 Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Wed, 30 Jun 2021 07:37:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- InterfaceStudy.App/InterfaceStudy.App.csproj | 12 ++ InterfaceStudy.App/Program.cs | 28 ++++ InterfaceStudy.Core/ChildA.cs | 16 ++ InterfaceStudy.Core/ChildB.cs | 17 ++ InterfaceStudy.Core/ExplicitBase.cs | 31 ++++ InterfaceStudy.Core/IBase.cs | 17 ++ InterfaceStudy.Core/ImplicitBase.cs | 23 +++ .../InterfaceStudy.Core.csproj | 7 + InterfaceStudy.Core/接口学习.md | 150 ++++++++++++++++++ InterfaceStudy.Test/BaseTest.cs | 19 +++ InterfaceStudy.Test/ChildATest.cs | 25 +++ InterfaceStudy.Test/ChildBTest.cs | 25 +++ InterfaceStudy.Test/DemoTest.cs | 65 ++++++++ .../InterfaceStudy.Test.csproj | 26 +++ InterfaceStudy.Test/UseXUnit.cs | 15 ++ InterfaceStudy.sln | 37 +++++ 16 files changed, 513 insertions(+) create mode 100644 InterfaceStudy.App/InterfaceStudy.App.csproj create mode 100644 InterfaceStudy.App/Program.cs create mode 100644 InterfaceStudy.Core/ChildA.cs create mode 100644 InterfaceStudy.Core/ChildB.cs create mode 100644 InterfaceStudy.Core/ExplicitBase.cs create mode 100644 InterfaceStudy.Core/IBase.cs create mode 100644 InterfaceStudy.Core/ImplicitBase.cs create mode 100644 InterfaceStudy.Core/InterfaceStudy.Core.csproj create mode 100644 InterfaceStudy.Core/接口学习.md create mode 100644 InterfaceStudy.Test/BaseTest.cs create mode 100644 InterfaceStudy.Test/ChildATest.cs create mode 100644 InterfaceStudy.Test/ChildBTest.cs create mode 100644 InterfaceStudy.Test/DemoTest.cs create mode 100644 InterfaceStudy.Test/InterfaceStudy.Test.csproj create mode 100644 InterfaceStudy.Test/UseXUnit.cs create mode 100644 InterfaceStudy.sln diff --git a/InterfaceStudy.App/InterfaceStudy.App.csproj b/InterfaceStudy.App/InterfaceStudy.App.csproj new file mode 100644 index 0000000..3e17cb8 --- /dev/null +++ b/InterfaceStudy.App/InterfaceStudy.App.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/InterfaceStudy.App/Program.cs b/InterfaceStudy.App/Program.cs new file mode 100644 index 0000000..fe62f3b --- /dev/null +++ b/InterfaceStudy.App/Program.cs @@ -0,0 +1,28 @@ +using System; + +namespace InterfaceStudy.App +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("接口的各种操作!"); + } + + /// + /// 隐式实现 + /// + public static void Test() + { + + } + + /// + /// 显式实现 + /// + public static void Test2() + { + + } + } +} diff --git a/InterfaceStudy.Core/ChildA.cs b/InterfaceStudy.Core/ChildA.cs new file mode 100644 index 0000000..f8f8ec9 --- /dev/null +++ b/InterfaceStudy.Core/ChildA.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace InterfaceStudy.Core +{ + public class ChildA : ExplicitBase, IBase + { + int Number = -1; + + public override int GetNumber() + { + return --Number; + } + } +} diff --git a/InterfaceStudy.Core/ChildB.cs b/InterfaceStudy.Core/ChildB.cs new file mode 100644 index 0000000..efb3320 --- /dev/null +++ b/InterfaceStudy.Core/ChildB.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace InterfaceStudy.Core +{ + public class ChildB : ExplicitBase + { + //可使用new关键字,表明有意隐藏继承成员 ExplicitBase.Number + int Number = -1; + + public override int GetNumber() + { + return --Number; + } + } +} diff --git a/InterfaceStudy.Core/ExplicitBase.cs b/InterfaceStudy.Core/ExplicitBase.cs new file mode 100644 index 0000000..011557a --- /dev/null +++ b/InterfaceStudy.Core/ExplicitBase.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace InterfaceStudy.Core +{ + /// + /// 基接口显式实现类 + /// + public class ExplicitBase : IBase + { + public int Number = 1; + + public ExplicitBase() + { + ++Number; + } + + int IBase.GetNumber() + { + Console.WriteLine("显式实现接口方法"); + return Number; + } + + public virtual int GetNumber() + { + Console.WriteLine($"基类与接口同名的虚方法!"); + return Number; + } + } +} diff --git a/InterfaceStudy.Core/IBase.cs b/InterfaceStudy.Core/IBase.cs new file mode 100644 index 0000000..6a332f4 --- /dev/null +++ b/InterfaceStudy.Core/IBase.cs @@ -0,0 +1,17 @@ +using System; + +namespace InterfaceStudy.Core +{ + /// + /// 基接口 + /// 1 接口中的对象都是公开权限的,否则接口无意义:不能使用范围修饰符(public private internal protected) + /// 2 接口对象可以是属性 方法 索引 事件 委托等,接口只包含定义不能包含实现,并且不能直接实例化接口。 + /// 3 接口对象不能是字段(字段本意为私有,与接口意义相背), + /// 4 不能有构造或析构函数(对象的创建与销毁,应该在实现类所关心的,接口只关心需要实现的功能[属性 方法 索引 事件 委托等]即可) + /// 5 不能有 static 修饰符,即对象不能是静态对象(静态的,本身就是实现;而接口是定义,是契约,只有实现了才有意义) + /// + public interface IBase + { + int GetNumber(); + } +} diff --git a/InterfaceStudy.Core/ImplicitBase.cs b/InterfaceStudy.Core/ImplicitBase.cs new file mode 100644 index 0000000..889efe6 --- /dev/null +++ b/InterfaceStudy.Core/ImplicitBase.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace InterfaceStudy.Core +{ + /// + /// 基接口隐式实现类 + /// + public class ImplicitBase : IBase + { + public int Number = 0; + + /// + /// 1 必须是public + /// 2 可以用自己修饰符:virtual + /// + public int GetNumber() + { + return Number; + } + } +} diff --git a/InterfaceStudy.Core/InterfaceStudy.Core.csproj b/InterfaceStudy.Core/InterfaceStudy.Core.csproj new file mode 100644 index 0000000..9f5c4f4 --- /dev/null +++ b/InterfaceStudy.Core/InterfaceStudy.Core.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/InterfaceStudy.Core/接口学习.md b/InterfaceStudy.Core/接口学习.md new file mode 100644 index 0000000..0ee3244 --- /dev/null +++ b/InterfaceStudy.Core/接口学习.md @@ -0,0 +1,150 @@ +# 接口学习 + +## 接口定义 + +> 接口是一种契约和规范;是指定一组对象的定义而非实现的引用类型;是C#实现多继承的机制;也是多态的一种常用实现方式。 + +## 接口特点 + +1. 接口可以包含属性、方法、索引器、委托与事件等对象,但不能包含字段,也不能包含构造或析构函数(对象的创建与销毁,应该在实现类所关心的,接口只关心需要实现的功能约定) +1. 接口中的对象都是公开权限的,否则接口无意义:不能使用范围修饰符(public private internal protected) +1. 不能有 static abstract virtual override sealed 等违反接口意义的修饰符 +1. 接口只包含对象的定义,不能包含对象的实现,也不能直接实例化接口 +1. 接口的实现类必须实现接口中的所有成员,除非实现类本身是抽象类(通过具体的可执行代码实现接口抽象成员的操作);接口实现子类中,可用new关键字隐藏父接口中的方法。 +1. 接口可以多继承,可用来解决C#类的单继承问题 +1. 接口名称一般都以“I”作为首字母,以与实现类区分 + +## 接口的隐式实现与显式实现 + ++ 接口 + +``` csharp + /// + /// 接口 + /// + public interface IBase + { + void Print(); + } +``` + ++ 隐式实现 +``` csharp + /// + /// 隐式实现接口 + /// + public class Base : IBase + { + //必须有访问修饰符 + //对象(方法)名,即是接口对象(方法)名 + public void Print() + { + Console.WriteLine($"隐式实现接口方法"); + } + } +``` + ++ 显式实现 +``` csharp + /// + /// 显式实现接口 + /// + public class Base : IBase + { + //不允许有访问修饰符 + //对象(方法)名为”接口名.对象(方法)名" + void IBase.Print() + { + Console.WriteLine("显式实现接口方法"); + } + } +``` + ++ 语法区别 + > 隐式实现必须加 *访问修饰符* 显式实现不能用任何*访问修饰符* ;隐式实现对象名是接口对象名,显式实现,对象名为*接口名.对象名* ++ 调用区别 + > 隐式实现,可以由实现类或接口类调用;显式实现只能由接口类调用。 + + ``` csharp + //隐式实现调用 + class Program + { + static void Main(string[] args) + { + //接口类可以调用 + IBase base = new Base(); + base.Print(); + + //实现类可以调用 + Base base2 = new Base(); + base2.Print(); + } + } + + //显式实现调用 + class Program + { + static void Main(string[] args) + { + //接口类可以调用 + IBase base = new Base(); + base.Print(); + + //实现类不能调用 + Base base2 = new Base(); + //语法错误,不可调用 + base2.Print(); + } + } + ``` + +小结: +1. 通常情况下,使用隐式方式实现接口; +2. 需要区分不同接口或者有同名对象时,使用显式实现; +3. 业务需要时,使用显式实现 + +## 接口继承 + +## 子类重复实现父类接口 +```csharp +/// +/// 接口 +/// +public interface IBase +{ + string GetA(); + string GetB(); +} + +/// +/// 接口实现基类 +/// +public class Base : IBase +{ + public string GetA() + { + return "基类 GetA方法"; + } + + public string GetB() + { + return "基类 GetB方法"; + } +} + +/// +/// 接口实现子类 +/// +public class ChildA:Base,IBase +{ + public string GetB() + { + return "实现子类 GetB方法"; + } +} + + + +``` + +## 运行时多态与编译时多态 \ No newline at end of file diff --git a/InterfaceStudy.Test/BaseTest.cs b/InterfaceStudy.Test/BaseTest.cs new file mode 100644 index 0000000..23995fd --- /dev/null +++ b/InterfaceStudy.Test/BaseTest.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Xunit; + +namespace InterfaceStudy.Test +{ + public class BaseTest + { + [Fact] + public void Test() + { + + } + } +} diff --git a/InterfaceStudy.Test/ChildATest.cs b/InterfaceStudy.Test/ChildATest.cs new file mode 100644 index 0000000..2487239 --- /dev/null +++ b/InterfaceStudy.Test/ChildATest.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using InterfaceStudy.Core; + +using Xunit; + +namespace InterfaceStudy.Test +{ + public class ChildATest + { + [Fact] + public void Test() + { + IBase a = new ChildA(); + + var number = a.GetNumber(); + + Assert.Equal(-2,number); + } + } +} diff --git a/InterfaceStudy.Test/ChildBTest.cs b/InterfaceStudy.Test/ChildBTest.cs new file mode 100644 index 0000000..b06467d --- /dev/null +++ b/InterfaceStudy.Test/ChildBTest.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using InterfaceStudy.Core; + +using Xunit; + +namespace InterfaceStudy.Test +{ + public class ChildBTest + { + [Fact] + public void Test() + { + IBase myBase = new ChildB(); + + var number = myBase.GetNumber(); + + Assert.Equal(2,number); + } + } +} diff --git a/InterfaceStudy.Test/DemoTest.cs b/InterfaceStudy.Test/DemoTest.cs new file mode 100644 index 0000000..95db59e --- /dev/null +++ b/InterfaceStudy.Test/DemoTest.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Xunit; + +namespace InterfaceStudy.Test +{ + public class DemoTest + { + [Fact] + public void Test() + { + IDemo demo = new DemoA(); + var result = demo.GetNumber(); + + Assert.Equal(2,result); + } + + [Fact] + public void Test2() + { + IDemo demo = new DemoB(); + var result = demo.GetNumber(); + + Assert.Equal(1,result); + + var demoB = new DemoB(); + var resultB = demoB.GetNumber(); + + Assert.Equal(3, resultB); + } + } + + public interface IDemo + { + int GetNumber(); + } + + public class Demo : IDemo + { + int IDemo.GetNumber() + { + return 1; + } + } + + public class DemoA : Demo, IDemo + { + public int GetNumber() + { + return 3; + } + } + + public class DemoB : Demo + { + public int GetNumber() + { + return 3; + } + } +} diff --git a/InterfaceStudy.Test/InterfaceStudy.Test.csproj b/InterfaceStudy.Test/InterfaceStudy.Test.csproj new file mode 100644 index 0000000..9b672cf --- /dev/null +++ b/InterfaceStudy.Test/InterfaceStudy.Test.csproj @@ -0,0 +1,26 @@ + + + + net5.0 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/InterfaceStudy.Test/UseXUnit.cs b/InterfaceStudy.Test/UseXUnit.cs new file mode 100644 index 0000000..5f100a1 --- /dev/null +++ b/InterfaceStudy.Test/UseXUnit.cs @@ -0,0 +1,15 @@ +using System; + +using Xunit; + +namespace InterfaceStudy.Test +{ + public class UseXUnit + { + [Fact] + public void Test1() + { + Assert.True(true,"ʹXUnit"); + } + } +} diff --git a/InterfaceStudy.sln b/InterfaceStudy.sln new file mode 100644 index 0000000..edc2537 --- /dev/null +++ b/InterfaceStudy.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31410.357 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InterfaceStudy.Core", "InterfaceStudy.Core\InterfaceStudy.Core.csproj", "{2F771F8A-B472-485D-816A-BB5B5C828DE2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InterfaceStudy.App", "InterfaceStudy.App\InterfaceStudy.App.csproj", "{5578DC19-F9A7-4FE0-AB74-6A583A30E99B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InterfaceStudy.Test", "InterfaceStudy.Test\InterfaceStudy.Test.csproj", "{B7B58056-A189-4628-BE74-A16165B04BF7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2F771F8A-B472-485D-816A-BB5B5C828DE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F771F8A-B472-485D-816A-BB5B5C828DE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F771F8A-B472-485D-816A-BB5B5C828DE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F771F8A-B472-485D-816A-BB5B5C828DE2}.Release|Any CPU.Build.0 = Release|Any CPU + {5578DC19-F9A7-4FE0-AB74-6A583A30E99B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5578DC19-F9A7-4FE0-AB74-6A583A30E99B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5578DC19-F9A7-4FE0-AB74-6A583A30E99B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5578DC19-F9A7-4FE0-AB74-6A583A30E99B}.Release|Any CPU.Build.0 = Release|Any CPU + {B7B58056-A189-4628-BE74-A16165B04BF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7B58056-A189-4628-BE74-A16165B04BF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7B58056-A189-4628-BE74-A16165B04BF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7B58056-A189-4628-BE74-A16165B04BF7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A49848D2-019D-499A-8950-BF411F1B7512} + EndGlobalSection +EndGlobal