C#中的接口

之前的学习中,学习了C#中的继承,但是C#并不支持多重继承,也就是说如果一个子类想要同时继承2个及以上基类的属性、方法,C#是不允许的。为了解决这个问题,C#用接口来“代替”多重继承。

接口:

接口是对一组方法声明的统一命名,但这些方法没有提供任何实现。也就是说,在接口中声明一组方法,但不提供实现,而继承该接口的类需要实现这些方法。比如说:一个“吃”接口中声明了很多方法:细嚼慢咽、狼吞虎咽、津津有味,但不能具体说明每种吃的方法是如何实现的。然后有一些类(小明、小王)继承了该“吃”接口,并要具体实现小明、小王的细嚼慢咽、狼吞虎咽、津津有味方法。

1.如何定义接口

接口的定义与类的定义类似,只是类使用class关键字,而接口使用interface关键字,如:public interface Eat. 然后,需要在接口中定义一些方法、属性等。
注意:
①接口中只能定义方法、属性、事件、索引器或者这4类成员的组合,不能定义字段、运算符重载、实例构造函数和析构函数;
②接口中定义方法时不能添加访问修饰符,因为接口中方法默认为public,且也不能显示的添加public;
③接口中的所有成员都默认是公共的,因此都不能再使用访问修饰符。

2.接口的继承

接口的继承与类的继承方法是一样的,定义完接口后,类使用“:”,后接接口名即可继承该接口。例如:

//定义接口
public interface Compare
{
    //声明方法,但不实现
    int CompareTo(object other)
    {
    }
} 
//定义类,并继承接口
public classs Person : Compare
{
    private int age;

    public int Age
    {
        get{return age;}
        set{age = value;}
    }

    //实现接口中的方法
    public int CompareTo(object value)
    {
        //若value中没有值,则返回1,表示当前对象比传入对象大
        if (value == null)  
        {
            return 1;
        }
        //若value有值,则强制把object类型转换为Person类型
        Person otherPerson = (Person)value;
        //把当前对象的Age属性与需要比较的对象的Age属性进行比较
        if (this.Age < otherPerson.Age)
        {
            return -1;
        }
        else if (this.Age > otherPerson.Age)
        {
            return 1;
        }
        else
            return 0;
    }
}

3.调用接口

在上面,我们定义了接口,并在类中继承了该接口,然后我们需要在Main中调用该接口,一种实现方法为先将类实例化,然后通过类实例“.”接口方法名(参数)来达到调用接口方法的目的。例如:

class Program
{
    static void Main(string[] args)
    {
        //类的实例化
        Person p1 = new Person();
        Person p2 = new Person();

        p1.Age = 20;
        p2.Age = 30;

        //调用接口方法,对p1和p2的年龄进行比较
        if (p1.CompareTo(p2) > 0)
        {
            Console.WriteLine("p1比p2大");
        }
        else if (p1.CompareTo(p2) < 0)
        {
            Console.WriteLine("p1比p2小");
        }
        else
        {
            Console.WriteLine("p1和p2一样大");
        }
         Console.Read();
    }
}

运行以上代码,结果为:
运行结果

显式接口:

在上面的接口实现方法中,使用的是隐式的接口实现方法,即在实现代码中没有指定实现哪个接口中的CompareTo方法。但是如果有多个接口,且每个接口中都定义了一个相同返回类型、相同名字的方法,则使用隐式接口实现会出现问题。因为程序无法判定调用的是哪个接口中的这个方法。例如:

//中文接口
interface Chinese
{
    //声明接口方法
    void Hello();
}
//英文接口
interface English
{
    //声明接口方法
    void Hello();
}
//Greeting类实现了两个接口
public class Greeting : Chinese, English
{
    //隐式接口实现
    public void Hello()
    {
        Console.WriteLine("你好");
    }
}
//隐式接口的实现
class Program 
{
    static void Main(string[] args)
    {
        Greeting greeting = new Greeting();

        //调用中文接口
        Chinese ChineseGreeting = (Chinese)greeting;
        greeting.Hello();
        //调用英文接口
        English EnglishGreeting = (English)greeting;
        greeting.Hello();

        Console.Read();
    }
}

运行以上代码,结果为:
运行结果
可以看到,不管调用的是哪个接口,程序调用的都是同一个方法实现,输出都为“你好”。

为了解决这个问题,我们需要使用显式接口来解决这种情况。显式接口的实现方法为:在类的方法中指明实现的是哪个接口的方法,并在调用接口时修改为接口实例调用即可。例如:
将以上代码的Greeting类实现修改为:

public class Greeting : Chinese, English
{
    //显式接口实现
    void Chinese.Hello()
    {
        Console.WriteLine("你好");
    }
    void English.Hello();
    {
        Console.WriteLine("Hello");
    }
}

调用接口部分修改为:

ChineseGreeting.Hello();
EnglishGreeting.Hello();

重新运行修改后的代码,结果为:
运行结果
可以看到,显式接口实现解决了命名冲突的问题。

注意:
①使用显式接口时,类方法实现中不能添加任何访问修饰符,因为成员默认为私有;
②使用显式接口时,因为成员默认为私有,不能通过类的对象进行访问,必须通过接口实例进行访问。

前面具体分析了隐式与显式接口实现方式两种情况,但何时需要使用哪种接口需要自行判断,判断方法为:
ⅰ.采用隐式接口实现时,类和接口都可以访问接口中的方法;而若采用显式接口实现方式,接口方法只能通过接口来完成访问,因为此时接口方法默认为私有。
ⅱ.当类实现单个接口时,通常使用隐式接口实现方式,这样类的对象可以直接去访问接口方法。
ⅲ.当类实现了多个接口,并且接口中包含相同的方法名称、参数和返回类型时,则应使用显式接口实现方式。即使没有相同的方法签名,在实现多个接口时,仍推荐使用显式的方式,因为这样可以标识出哪个方法属于哪个接口。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值