C#3.0中的“多重继承”

摘要:
C#的对象系统是一个单一的根系统,不支持类的多重继承,只支持多接口实现,这在一定程度上带来了一些不便:我们在系统设计中经常抽象一些接口,并为接口提供一个抽象类作为默认实现,然后可以从抽象类导出实际类。如果一个类实现了多个接口,我们只能选择一个抽象类作为祖先类,然后手动将其他接口的实现添加到该类中。这种情况在C#3.0中已经改变。现在我们可以使用C#3.0的扩展方法来实现“受限多重继承”
    C#的对象系统是个单根系统,不支持类的多继承,只支持多接口实现,这在某种程度带来了一些不便:我们在系统设计时经常会抽象出一些接口,并为接口提供一个抽象类作为默认的实现,然后实际使用的类可以从抽象类派生。如果一个类实现了多接口,那我们只能选择一个抽象类作为祖先类,再将其他接口的实现手工加到类中。

    这种情况在C#3.0中有了变化,我们现在可以利用C#3.0的扩展方法来实现一个“受限的多继承”。

    C#3.0中引入了扩展方法,可以利用一个静态类的静态方法为一个类或者接口添加方法,关键是添加的方法是包含实现的,由此我们可以在C#3.0中为接口提供一个带实现的方法声明,而无需额外的实现类!如果一个类实现了多个这样的接口,就可以达到类似多继承的效果。

    让我们用代码测试一下:

C#3.0中的“多重继承”第1张using System;
C#3.0中的“多重继承”第1张
using System.Collections.Generic;
C#3.0中的“多重继承”第1张
using System.Linq;
C#3.0中的“多重继承”第1张
using System.Text;
C#3.0中的“多重继承”第1张
C#3.0中的“多重继承”第1张
namespace Test35
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张    
public interface ITestAC#3.0中的“多重继承”第9张{ }
C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第13张    
public static class ITestAHelper
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
public static void TestA(this ITestA obj)
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Console.WriteLine(
"ITestAHelper.TestA");
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第23张    }

C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张    
public interface ITestBC#3.0中的“多重继承”第9张{ }
C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第13张    
public static class ITestBHelper
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
public static void TestB(this ITestB obj)
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Console.WriteLine(
"ITestBHelper.TestB");
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第23张    }

C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第13张    
public class Test : ITestA, ITestB
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第23张    }

C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第13张    
class Program
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
static void Main(string[] args)
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Test obj1 
= new Test();
C#3.0中的“多重继承”第13张            obj1.TestA();
C#3.0中的“多重继承”第13张            obj1.TestB();
C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第13张            Console.ReadKey();
C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第23张    }

C#3.0中的“多重继承”第64张}

C#3.0中的“多重继承”第1张

    执行的结果:
   ITestAHelper.TestA     
   ITestBHelper.TestB
  
  


    ok!再多试一下,看看如果实现类中定义相同的方法会怎么样:

C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    public interface ITestA C#3.0中的“多重继承”第9张{ }
C#3.0中的“多重继承”第1张    
public static class ITestAHelper
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
public static void TestA(this ITestA obj)
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Console.WriteLine(
"ITestAHelper.TestA");
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第64张    }

C#3.0中的“多重继承”第1张
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    
public interface ITestB C#3.0中的“多重继承”第9张{ }
C#3.0中的“多重继承”第1张    
public static class ITestBHelper
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
public static void TestB(this ITestB obj)
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Console.WriteLine(
"ITestBHelper.TestB");
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第64张    }

C#3.0中的“多重继承”第1张
C#3.0中的“多重继承”第1张    
public class Test : ITestA, ITestB
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
//此方法与ITestA的TestA()扩展方法相同
C#3.0中的“多重继承”第13张
        public void TestA()
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Console.WriteLine(
"Test.TestA");
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第64张    }

C#3.0中的“多重继承”第1张
C#3.0中的“多重继承”第1张    
class Program
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
static void Main(string[] args)
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Test obj1 
= new Test();
C#3.0中的“多重继承”第13张            
//下面分别测试2种TestA()调用方式
C#3.0中的“多重继承”第13张
              obj1.TestA();
C#3.0中的“多重继承”第13张            ((ITestA)obj1).TestA();
C#3.0中的“多重继承”第13张
C#3.0中的“多重继承”第13张            Console.ReadKey();
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第64张    }

C#3.0中的“多重继承”第1张

   执行的结果:
   Test.TestA     
   ITestAHelper.TestA
 
 

    从这次的结果看,这里有一点点问题,如果实现类有相同的方法,接口的扩展方法总是被接口的实现类隐藏,那么如何多态?加上virtual试试看,似乎static方法是不能使用virtual修饰符的:

C#3.0中的“多重继承”第1张        public static virtual void TestA(this ITestA obj)
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Console.WriteLine(
"ITestAHelper.TestA");
C#3.0中的“多重继承”第64张        }

C#3.0中的“多重继承”第1张

    编译出错,看来此路不通。

    再多试一下,如果接口中也定义相同的方法会这么样?

C#3.0中的“多重继承”第1张    public interface ITestA 
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
void TestA();
C#3.0中的“多重继承”第64张    }

C#3.0中的“多重继承”第1张
C#3.0中的“多重继承”第1张    
public static class ITestAHelper
C#3.0中的“多重继承”第7张C#3.0中的“多重继承”第8张    
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张        
public static void TestA(this ITestA obj)
C#3.0中的“多重继承”第10张C#3.0中的“多重继承”第11张        
C#3.0中的“多重继承”第9张{
C#3.0中的“多重继承”第13张            Console.WriteLine(
"ITestAHelper.TestA");
C#3.0中的“多重继承”第23张        }

C#3.0中的“多重继承”第64张    }

C#3.0中的“多重继承”第1张

   执行的结果:
   Test.TestA    
     Test.TestA 

    看来这样的话,扩展方法似乎总是被藏在接口的实现方法后面了,我没想出在接口变量中有什么方法可以访问到它。或许Reflection可以?我没有尝试下去。

    接口和类的方法声明可以和扩展方法相同,那一个类能不能实现2个拥有相同的扩展方法的接口呢?测试结果是编译错误,代码比较简单,有兴趣的朋友可以自己试试看。

    在此做个小小的总结,利用C#3.0的扩展方法,我们可以为接口提供默认的实现而无需定义一个实现类,如果一个类实现了多个这样的接口,就可以达到类似“多重继承”的效果。但是这种方法也有局限性,因为static方法不能使用virtual修饰符,所以接口的扩展方法只能被接口的实现类隐藏,而不能重写,无法实现多态的效果,这是个比较大的缺点。这点如果能解决,就完美了。没办法,这个世界没有完美的东西啊。C#3.0中的“多重继承”第152张

   

  

免责声明:文章转载自《C#3.0中的“多重继承”》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用autotools自动生成Makefile并在此之上使用dh-make生成可发布的deb程序包(详解)MySQL分区表(转)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Vue + Element UI 实现权限管理系统 前端篇(十):动态加载菜单

动态加载菜单 之前的 导航树 是写死的,实际应用中需要从后台服务器获取菜单数据之后动态生成。 之前的mock已经准备好了模拟数据 接口模块化 之前说过,当接口变多时,放在一个 interface.js 中不方便维护。 现在改名为 api.js 作为集合文件,将里面的 相关接口 都转入新的文件夹 modules 里面。  模块化之后,模块接口写在相应的模块...

微信支付开发教程

本文介绍微信支付v2和v3版的微信支付开发教程,来源于微信公众平台官方网站。 原文:http://www.cnblogs.com/txw1958/p/wxpay-development-document.html 前言 微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请的为v3版。V3版的微信支付没有paySignKey参数。...

接口testing需要的技能

1、什么是接口测试? 定义:测试系统组件间接口的一种测试。主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点,重点是检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等; 目的:测试接口的正确性和稳定性; 原理:模拟客户端向服务器发送请求报文,服务器接收请求报文后对相应的报文做处理并向客户端返回应答,客户端接收应答的过程; 重点:检...

Java SPI

一、什么是Java SPI?   SPI的全名为Service Provider Interface.大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的。在java.util.ServiceLoader的文档里有比较详细的介绍。简单的总结下java spi机制的思想。我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块...

Java SPI机制

最近在一个日志标准化的项目中,使用了责任链模式来链接每一个具体的处理Handler.但是在实例化时,需要每一个都去创建实例。如: /** * 初始化具体的处理类 */ private void initConcreteHandler() { handlers.add(new BasicParamHandler()); hand...

php使用curl方法请求java接口

CURL是一个非常强大的开源库,支持很多协议,我们可以使用curl方法解决PHP请求JAVA接口直线导轨滑台 1.通过POST方法请求java接口: 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 functionhttp_post_advertise($...