关于接口的一些事---接口基础

一、定义接口

interface IShowMessage
{
  
void Show(string strMesg);
}

在C#中是用interface关键字定义接口,为其指定一个名称和一组实例方法签名。还可以定义事件、无参数的属性和索引器。但需要注意以下3点:
1、C#会阻止接口定义任何一种静态成员。
2、根据规范,接口类型名称要使用一个大写字母I作为前缀,在源代码中识别其为接口类型。
3、接口可以继承其它接口,但是接口继承的工作方式与类继承的工作式不一样,可以将接口继承想象为包含其他接口的约定。在FCL中ICollection<T>接口定义便继承了IEnumerable<T>和IEnumerable这两个接口,这意味着: 继承自ICollection<T>接口的类必须同时实现ICollection<T>、IEnumerable<T>、IEnumerable这3个接口定义的所有方法。也可以这样说,期望一个对象的类型实现ICollection<T>接口的所有方法,同时要求该对象的类型还必须要实现了IEnumerable<T>、IEnumerable接口的方法。


二、接口的继承

    class Demo : IShowMessage
    
{
        
public void Show(string strMesg)
        
{
            Console.WriteLine(
"You show the message : {0}", strMesg);
        }

    }

以上的代码就是演示了一个Demo类继承了IShowMessage接口,并将实现了此接口中所定义的方法。C#编译器要求将实现的方法标记为public。如果在源代码中没有显式将接口方法标记为Virtual,编译器会把它们标记为virtual和sealed,这会阻止派生类重写接口方法。以下的例子会产生编译错误。 

    class Demo : IShowMessage
    
{
        
//没有显示将方法标记为virtual,所以NewDemo类重写该接口方法时就会产生编译错误。
        public void Show(string strMesg)
        
{
            Console.WriteLine(
"You show the message : {0}", strMesg);
        }

    }


    
class NewDemo : Demo
    
{
        
public override void Show(string strMesg)
        
{
           Console.WriteLine(
"The message in the NewDemo : {0}",strMesg);
        }

    }
;

但是通过一种变通的方法实现重新实现基类的接口方法,因为派生类可以重新继承同一个接口,并为该接口的方法提供自己的实现。

    class NewDemo : Demo,IShowMessage
    
{
        
new public void Show(string strMesg)
        
{
           Console.WriteLine(
"The message in the NewDemo : {0}",strMesg);
        }

    }
;

三、调用接口方法详解

    interface IShowMessage
    
{
        
void Show(string strMesg);
    }


    
interface IShow
    
{
        
void ShowName(string strName);
    }


    
class Demo : IShowMessage,IShow
    
{
        
public void Show(string strMesg)
        
{
            Console.WriteLine(
"You show the message : {0}", strMesg);
        }

        
public void ShowName(string strName)
        
{
            Console.WriteLine(
"My Name is {0}", strName);
        }

    }

以上的Demo类继承了IShow、IShowMessage两个接口,并实现两个接口中定义的全部方法,然后再看以下代码我们进一步分析:

    class DemoFactory
    
{
        
public static Demo CreateDemo()
        
{
            
return new Demo();
        }

    }


    
class Program
    
{
        
public static void Main()
        
{            
            IShowMessage sm 
= DemoFactory.CreateDemo();
            sm.Show(
"I am successful!");
            IShow s 
= DemoFactory.CreateDemo();
            s.ShowName(
"Kenny");
            Demo demo 
= DemoFactory.CreateDemo();
            demo.Show(
"I am successful!");
            demo.ShowName(
"Kenny");
        }

    }

代码中的sm是IShowMessage接口类型变量,它可以调用属于IShowMessage的Show()方法,除了这个方法还有没有其它方法可以调用?答案是肯定的!有。System.Object类型中的方法sm也能调用,在FCL中所有类型都派生于Object类型。除此以外就没有其他方法可以调用了。如果用sm去调用ShowName()方法,保证会出现编译错误。同理,s也只能调用IShow接口中的方法和Object中的方法。Demo类的实列对象可以同时调用IShow与IShowMessage接口类型中的方法,同样也可以调用Object中的方法咯。(发觉自己有点啰嗦)
 
一点提示:值类型也可以实现接口。不过、在将值类型的实例转换为一个接口类型时,值类型的实例必须是装箱的。因为接口变量是必须指向堆上一个对象的一个引用,以便CLR能检查对象的类型对象指针来判断对象的确切类型。然后、在调用一个已装箱的值类型的接口方法时,CLR会跟随对象的类型对象指针,找到该类型对象的方法表,以调用正确的方法。

posted on 2007-07-06 17:36  Ah Yuan  阅读(438)  评论(0编辑  收藏  举报