【一文了解】C#基础-接口

目录

1. 定义

2. 接口的特点与规则

3. 接口的实现

3.1单接口实现

3.2多接口实现

4. 接口的作用和用途

1)扩展行为

2)规范行为

3)降低耦合

5. 接口与继承的比较

1)继承

2)接口

6. 接口与抽象类的比较

1)IComparable(比较器,常用)

2)IComparer(比较器)

3)IEnumerable(枚举器,常用)

4)IEnumerator(枚举器)


       本篇文章来分享一下C#的接口。从接口的定义、特点与规则、接口的实现、接口与继承的比较、接口与抽象类的比较等来详细学习接口。

1. 定义

       在C#中,接口(interface)是用来定义类或结构(struct)所实现的一组公共行为的抽象。接口本质上定义了行为规范,但不实现行为。接口中的所有成员都是抽象的,它们只声明不实现,所有成员默认是public,不能有字段,也不能有实现代码。接口名建议用”I”开头,其后单词首字母大写 ,如IFlyable,IDriveable

public interface IFlyable
{
    void Fly();//接口中的方法默认是抽象的
}

       简而言之,接口是规范,定义一组对外的行为规范,要求它的实现类必须实现接口的所有成员。其中实现接口的方法不能加override。

 

2. 接口的特点与规则

1)接口中不能包含字段:接口只能包含方法、属性、索引器和事件,不能包含任何字段。
2)所有成员默认是public:接口中的方法、属性、事件等成员默认是public,不能显式指定访问修饰符。接口的成员不能有访问修饰符,也不能使用abstract关键字。

public interface IDriveable
{
    void Drive();//无需使用abstract,默认即为抽象方法
}

3)接口中只能定义抽象成员:接口的所有成员默认都是抽象的,因此不需要再使用abstract关键字显式声明。
4)接口不能实例化:接口无法直接创建实例,必须通过实现接口的类或结构来创建对象。如,接口 iObj=new 实现类();

 

3. 接口的实现

3.1单接口实现

       实现接口时,类必须实现接口中的所有成员,否则该类会被标记为抽象类。

public class Car : IDriveable
{
    public void Drive()
    {
        Console.WriteLine("Driving...");
    }
}


3.2多接口实现

       C#允许类实现多个接口,接口之间的多继承是允许的。实现类必须实现接口中的所有成员。包括隐式实现与显式实现。

1)隐式实现:最常见的实现方式,直接实现接口中的成员,默认是public。
2)显式实现:通过接口名称显式实现接口成员,且这些成员在实现类中是private的,只有通过接口类型的引用才能调用。

//隐式实现
public class Car : IDriveable, IFlyable
{
    public void Drive() => Console.WriteLine("Driving...");
    public void Fly() => Console.WriteLine("Flying...");
}
//显式实现
public class Car : IDriveable, IFlyable
{
    void IDriveable.Drive() => Console.WriteLine("Driving...");
    void IFlyable.Fly() => Console.WriteLine("Flying...");
}

       =>被称为表达式主体运算符,是一种简洁的语法,用于将方法、属性、索引器等成员的实现压缩为单行代码,适用于那些仅包含单一表达式的成员。

 

4. 接口的作用和用途

1)扩展行为

       接口允许你在不改变已有类的情况下,扩展类的功能。例如,假设有一个Car类,它没有飞行功能,但我们可以通过实现IFlyable接口,给Car类增加飞行的功能,而不必直接修改原类。

2)规范行为

       接口允许我们定义一组行为的规范,使得不同类在行为上保持一致。例如,不同种类的交通工具(汽车、飞机、船只等)都可以实现IDriveable接口,这样我们可以用统一的方式对不同的交通工具进行操作。

3)降低耦合

       接口允许代码与实现细节解耦,增强代码的可扩展性和可维护性。使用接口可以降低类与类之间的直接依赖,便于未来的扩展和修改。

 

5. 接口与继承的比较

1)继承

①类继承只能支持单一继承。一个类只能继承自一个父类。
②类继承是继承父类的具体实现,并可能重写某些方法。

//父类(基类)
public class Animal
{
    public string Name { get; set; }
    
    //父类方法
    public void Eat()
    {
        Console.WriteLine($"{Name} is eating.");
    }
    
    //虚方法,允许子类重写
    public virtual void Speak()
    {
        Console.WriteLine($"{Name} makes a sound.");
    }
}

//子类(派生类)
public class Dog : Animal
{
    public string Breed { get; set; }

    //重写父类方法
    public override void Speak()
    {
        Console.WriteLine($"{Name} barks.");
    }
}

public class Program
{
    public static void Main()
    {
        Dog dog = new Dog { Name = "Buddy", Breed = "Golden Retriever" };
        dog.Eat();//继承自父类的方法,输出:Buddy is eating.
        dog.Speak();//重写后的方法,输出:Buddy is eating.
    }
}

2)接口

①接口支持多继承,一个类可以实现多个接口。
②接口只定义行为规范,不关心实现细节,避免了类之间紧耦合。

public interface IAnimal
{
    void Eat();
    void Sleep();
}
public interface ISwimmable
{
    void Swim();
}

//类实现多个接口
public class Duck : IAnimal, ISwimmable
{
    public void Eat()
    {
        Console.WriteLine("Duck is eating.");
    }

    public void Sleep()
    {
        Console.WriteLine("Duck is sleeping.");
    }

    public void Swim()
    {
        Console.WriteLine("Duck is swimming.");
    }
}

public class Program
{
    public static void Main()
    {
        Duck duck = new Duck();
        duck.Eat();//实现自 IAnimal 接口,输出:Duck is eating.
        duck.Sleep();//实现自 IAnimal 接口,输出:Duck is sleeping.
        duck.Swim();//实现自 ISwimmable 接口,输出:Duck is swimming.
    }
}
特性继承(Class)接口(Interface)
继承结构单继承:一个类只能继承自一个父类支持多继承:一个类可以实现多个接口
实现细节继承父类的实现,子类可以重写父类的方法只定义行为规范,不关心实现细节
使用场景用于描述类之间的“是一个”关系(例如:狗是动物)用于定义不同类可以共享的行为(例如:可游泳的动物)
访问修饰符可以使用访问修饰符(public, private等)所有成员默认是公共的(public)
构造函数可以有构造函数接口不能有构造函数

总结:
类与类:只能单继承。
类与接口:可以多实现(一个类可以实现多个接口)。
接口与接口:可以多继承(一个接口可以继承多个接口)。

 

6. 接口与抽象类的比较

 1)接口:当需要定义一个行为的规范,并允许多个类实现该行为时,使用接口。例如,IDriveable接口可以被多个类(如Car、Truck)实现。

//定义接口 IDriveable
public interface IDriveable
{
    void Drive();  // 接口方法,只定义行为的规范,不提供实现
}

//类 Car 实现 IDriveable 接口
public class Car : IDriveable
{
    public void Drive()
    {
        Console.WriteLine("The car is driving.");
    }
}

//类 Truck 实现 IDriveable 接口
public class Truck : IDriveable
{
    public void Drive()
    {
        Console.WriteLine("The truck is driving.");
    }
}

public class Program
{
    public static void Main()
    {
        IDriveable car = new Car();
        car.Drive();//调用 Car 类中的 Drive 方法,输出:The car is driving.

        IDriveable truck = new Truck();
        truck.Drive();//调用 Truck 类中的 Drive 方法,输出:The truck is driving.
    }
}

2)抽象类:当希望定义一些通用的行为,并允许一些方法在子类中被重写时使用抽象类。例如,Animal类可以是抽象类,包含一些通用的行为(如Eat方法),同时定义一些抽象方法(如MakeSound方法)。

//定义抽象类 Animal
public abstract class Animal
{
    //已实现的通用方法
    public void Eat()
    {
        Console.WriteLine("The animal is eating.");
    }

    //抽象方法,要求子类实现
    public abstract void MakeSound();
}

//类 Dog 继承 Animal,并实现 MakeSound 方法
public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Dog Wangwang.");
    }
}

//类 Cat 继承 Animal,并实现 MakeSound 方法
public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Cat MiaoMiao.");
    }
}

public class Program
{
    public static void Main()
    {
        Animal dog = new Dog();
        dog.Eat();//调用父类 Animal 中的 Eat 方法,输出:The animal is eating.
        dog.MakeSound();//调用子类 Dog 中的 MakeSound 方法,输出:Dog Wangwang.

        Animal cat = new Cat();
        cat.Eat();//调用父类 Animal 中的 Eat 方法,输出:The animal is eating.
        cat.MakeSound();//调用子类 Cat 中的 MakeSound 方法,输出:Cat MiaoMiao.
    }
}
特性接口(Interface)抽象类(Abstract Class)

成员实现

不能包含实现,所有成员默认为抽象的

可以包含实现和抽象方法

字段不能包含字段可以包含字段
多继承支持一个类可以实现多个接口不支持多继承,一个类只能继承一个抽象类
方法实现接口的方法只能声明,不能提供实现抽象类可以有部分实现,也可以有抽象方法
构造函数接口不能有构造函数抽象类可以有构造函数
访问修饰符接口成员默认是 public,不能使用其他访问修饰符抽象类可以定义不同的访问修饰符
使用场景用于定义一组行为规范,多个类可以实现这些行为用于定义类的通用行为,允许部分实现并强制子类实现抽象方法

       简而言之,接口更多用于行为的抽象,而抽象类则更多用于功能的抽象和实现。想要更详细了解继承和抽象类的有关知识,可以参考【超详细】C#基础-面向对象三大特性:封装、继承


7. 接口在C#中的应用

       C#中有很多常用的接口,帮助我们统一不同类的行为。以下是一些常见的接口:

1)IComparable(比较器,常用)

       类内继承,通过实现CompareTo方法来自定义对象的比较规则,用于比较对象的大小。

2)IComparer(比较器)

       比较器继承,通过实现Compare方法,自定义两个对象的比较规则,常用于排序比较。

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

namespace InterfacePro
{
    //调用端
    class Program
    {
        static void Main(string[] args)
        {
            Student zs = new Student
            {
                Id = 1001,
                Age = 19,
                Weight = 140
            };
            Student ls = new Student
            {
                Id = 1002,
                Age = 18,
                Weight = 160
            };

            //写法1:自定义对象的比较
            int a = zs.Age.CompareTo(ls.Age);
            //写法2:一般做法,自定义的类只选择一个属性去比较,实现比较接口IComparable
            int b =  zs.CompareTo(ls);
            //写法3:基于写法2,如果还要比较其他属性,因为要遵守开闭原则,此时要实现另一个比较器
            WeightCompare weightCom = new WeightCompare();
            int c = weightCom.Compare(zs,ls);
        }
    }

    //定义端 复用
    class Student:IComparable
    {
        public int Id { get; set; }
        public int Age { get; set; }
        public int Weight { get; set; }

        public int CompareTo(object obj)
        {
            return this.Id.CompareTo((obj as Student).Id);
        }
    }
    class WeightCompare : IComparer
    {
        public int Compare(object x, object y)
        {
            return (x as Student).Weight.CompareTo((y as Student).Weight) ;
        }
    }
}


3)IEnumerable(枚举器,常用)

       通过实现GetEnumerator方法返回一个迭代器IEnumerator,使类型支持简单迭代(foreach)。

4)IEnumerator(枚举器)

       本质是一组yield return的语句,通过MoveNext进行逐段访问,自己可以控制迭代的节奏。

public class MyCollection : IEnumerable
{
    private int[] items = { 1, 2, 3 };

    public IEnumerator GetEnumerator()
    {
        foreach (var item in items)
        {
            yield return item;
        }
    }
}

 

       好了,本次的分享到这里就结束啦,希望对你有所帮助~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值