关于接口的多态性问题 接口的实现

这里关于接口的定义和为什么使用接口不做多说,大家也都知道。

 

下面主要说一下关于接口的使用过程中关于多态性问题,这个是我比较关注的问题。

 

  1. 接口的限制

不允许在接口中包含任何字段,即使是static字段。

不允许在接口中包含任何构造函数。

不允许在接口中包含任何析构函数。

不允许为接口中的任何方法指定访问修饰符。

不允许在接口中嵌套任何类型。

不允许从结构或者类中继承一个接口,虽然一个接口能从另一个接口继承。

 

下面给出一个我们即将用到的简单的接口的定义:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{
    interface IWork
    {
        void test();
        int count(int index);
    }
}


 

注意一个良好的编程习惯: 定义的接口以 I 开头,这样可以清楚的区分接口和其他类。

 

接口的实现

接口的实现可以分为两种,显示实现接口和非显示的实现接口。

 

显示实现接口

使用接口名做为方法名的前缀,成为显示接口实现,也是我们应该养成的一个编程习惯。(但是我自己的练习中发现显示实现的接口无法实现多态性,可能规定的就不能实现多态性,这点接下来会讲)

 

用于实现一个接口的所有的方法都必须有public 的访问型,但是,如果你是显示的实现接口,则不可以为显示实现的接口指定访问修饰符。

 

使用显示实现的接口不能声明为 virtual ,但在省略接口名以后则可以声明为virtual.

因为显示实现的接口不能声明为 virtual ,所以显示实现的接口不能实现多态性。但是显示接口的实现有很多优势,可以写出更清晰更容易维护的代码,增强可预测性。如果一个类实现的多个接口中有相同的函数的声明,这样我们只有通过显示的实现接口来避免歧义。

 

需要注意的一点:显示实现接口以后,这个显示的实现的接口默认具有 public 可访问性,对实现的接口的方法的访问,只能通过接口名来访问,不能通过实现接口类的实例对象来访问,实例对象是找不到显示实现的接口的方法的。只有通过一个接口类型的变量引用实现接口的类的对象,并通过这个接口引用访问类中实现的接口方法。

 

显示实现的接口:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{
    class MyWork:IWork
    {
        public MyWork()
        {
        }

        void IWork.test()
        {
            Console.WriteLine("interface test");
            //throw new NotImplementedException();
        }

        int IWork.count(int index)
        {
            Console.WriteLine("interface count");
            //throw new NotImplementedException();
            return 0;
        }
    }

    class SonOfMyWork : MyWork
    {
        public SonOfMyWork()
            : base()
        {
            Console.WriteLine("class : SonOfMyWork");
        }

        public virtual void test()
        {
            Console.WriteLine("SonOfMyWork, interface explicitly completed.");
        }
    }
}


在 MyWork 这个类中,接口都是显示实现的,在SonOfMyWork中,继承了MyWork, 并且重新声明了 test() 函数。

下面看一下运行结果:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            MyWork myWork = new MyWork();
            IWork work = myWork;
            work.test();
            work.count(5);

            Console.WriteLine("");
            SonOfMyWork son = new SonOfMyWork();
            son.test();
            Console.WriteLine("");
            work = son;
            work.test();

            //Console.WriteLine("/");
            //MyWork2 myWork2 = new MyWork2();
            //myWork2.test();

            //Console.WriteLine("/");
            //SonOfMyWork2 son2 = new SonOfMyWork2();
            //son2.test();
            //work = son2;
            //work.test();
        }
    }
}


work.test(); 这里通过接口调用方法,输出的结果就是接口的显示实现。

son.test(); 因为son 对象是继承于MyWork ,  SonOfMyWork 定义的test() 方法已经隐藏了父类的方法,所以调用的是在SonOfMyWork 类中定义的test() 方法。 这里也说明了接口的显示实现不能实现多态性,但是以后在有类继承SonOfMyWork 类的时候,就可以再次将test() 实现多态性。

 

work = son;            work.test(); 这里通过接口访问实现接口类的派生类,用来测试接口的多态性,注意,这里的输出是接口的显示实现中输出的语句,并没有访问到这个派生类中的test() 方法,而是访问的接口的显示实现的类中的方法。

以下是上面程序的输出:

interface test
interface count

class : SonOfMyWork
SonOfMyWork, interface explicitly completed.

interface test
请按任意键继续. . .

 

上面的程序可以看到接口的显示实现不能实现多态性,但是接口的显示实现确实有很多好处,应该注意接口的显示实现。

 

接口的隐式实现

下面的类是关于接口的隐式实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{
    class MyWork2:IWork
    {
        public virtual void test()
        {
            Console.WriteLine("Interface implicitly implement.");
            //throw new NotImplementedException();
        }

        public virtual int count(int index)
        {
            //throw new NotImplementedException();
            return 0;
        }
    }

    class SonOfMyWork2 : MyWork2
    {
        public override void test()
        {
            //base.test();
            Console.WriteLine("Interface in SonOfMyWork2");
        }
    }
}

接口的隐式实现就可以声明为public, virtual 的,并且可以实现多态性。

 

关于隐式实现的测试代码:

 

            Console.WriteLine("/");
            MyWork2 myWork2 = new MyWork2();
            myWork2.test();

            Console.WriteLine("/");
            SonOfMyWork2 son2 = new SonOfMyWork2();
            son2.test();
            work = son2;
            work.test();


work = son2;work = son2; 通过接口引用实现接口的类的派生类的对象。

输出结果:

 

/
Interface implicitly implement.
/
Interface in SonOfMyWork2
Interface in SonOfMyWork2
请按任意键继续. . .

这里可以看到隐式实现的接口中,通过对象访问test() 方法和通过接口对派生类对象的引用调用test() 方法都有一致的输出,可以证明隐式实现的接口可以实现多态性。

 

特别说明:对于这个网页排版工具我不是很会用,所以文章写的有点排版乱,以后尽量的用熟这个工具,避免大家看的不舒服。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值