您的位置:首页 > 编程语言 > C#

C#基本语法学习(九)

2016-03-18 18:15 351 查看
[b]C#中的接口[/b]

  在C#中接口是一组公共方法或属性的集合。接口可以被其他接口或是类继承,但不能被实例化。

    1、接口中包含的属性和方法都是公共的,不是继承或是私有的。事实上,在C#中定义接口中的成员时,不允许显示指定接口成员的可访问性,而是自动默认为公共的。

    2、接口中只能包含普通方法或属性,而不能包含其他内容,如构造函数、变量等。

    3、当接口被某个类继承时,通常说类实现了这个接口,而较少说类继承了接口。

    4、接口中的方法和属性只有签名部分,而没有实现部分,甚至连接口名后面的大括号也不能有,否则会出现编译错误。

  在C#中用interface关键字定义一个接口

  访问修饰符 interface 接口名

  {

    //接口成员(方法和属性)

  }

  C#中约定接口的名字以字母I开头。如以下代码定义一个接口IPerson

public interface IPerson
{
void eat(object food);      //接口的方法
void speak(string text);    //接口的方法

string name                 //接口的属性
{
get;
set;
}
}


  如前所述,接口中不允许定义变量、构造函数,不能显示指定接口中方法或属性的可访问性。

  接口可以被类或者别的接口继承。类继承接口的语法与类继承类的语法相同,都是在类名后面加冒号和要继承的接口名,如下:

  访问修饰符 class 类名:接口名

  {

    //类与接口的成员

  }

  类继承接口与类继承类的不同之处在于一个类可以同时继承多个接口,但只能从一个类继承。当一个类继承多个接口时,多个接口之间用逗号隔开,如下:

  访问修饰符 class 类名:[基类名][,接口1][,接口2][...][,接口n]

  {

    //类与接口成员

  }

  接口继承接口与类继承接口语法类似,只是定义接口时使用关键字interface。

  访问修饰符 interface 接口名:[接口1][,接口2][,接口3][...][,接口n]

  {

    //接口成员

  }

  如果一个类从接口继承,那么这个类必须要实现接口中定义的所有方法和属性。由于接口定义了方法和属性的签名,而这些方法和属性的具体实现代码是在从接口继承的类里写,所以当一个类从接口继承时,通常说一个类实现了某个接口。

  这里所说的实现有两层含义:首先说明类继承于接口,其次,类中用代码实现了接口中定义的方法和属性。

  如果一个类实现了一个接口,由于类继承自接口,所以类可以隐式转换为接口,这与派生类向基类隐式转换是一样的。如果一个类实现了多个接口,那么类可以隐式转换为其中任意一个接口。

public interface IPerson
{
void eat(object food);      //接口的方法
void speak(string text);    //接口的方法

string name                 //接口的属性
{
get;
set;
}
}

public class Student:IPerson
{

public void eat(object food)
{
Console.WriteLine(name + " eat: " + food.ToString());
}

public void speak(string text)
{
Console.WriteLine(name + " say: " + text);
}

private string _name;
public string name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
static void Main(string[] args)
{
IPerson person;
Console.WriteLine("Main: 通过接口调用方法");
person = new Student();
person.name = "Nick";
person.eat("apple");
person.speak("Hello");
Console.WriteLine("Main: 通过类调用方法");
Student s = new Student();
s.name = "Jessice";
s.eat("rice");
s.speak("Hehe");

Console.ReadLine();
}


  结果

Main: 通过接口调用方法
Nick eat: apple
Nick say: Hello
Main: 通过类调用方法
Jessice eat: rice
Jessice say: Hehe


  显式接口的实现

  使用显式接口时,类中用来实现接口的方法名前面必须以接口名作为前缀。  

public class NewStudent:IPerson
{

void IPerson.eat(object food)
{
Console.WriteLine(_name + " eat: " + food.ToString());
}

void IPerson.speak(string text)
{
Console.WriteLine(_name + " say: " + text);
}

private string _name;
string IPerson.name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
static void Main(string[] args)
{
IPerson person;
Console.WriteLine("Main: 通过接口调用方法");
person = new Student();
person.name = "Nick";
person.eat("apple");
person.speak("Hello");
Console.WriteLine("Main: 通过类调用方法");
Student s = new Student();
s.name = "Jessice";
s.eat("rice");
s.speak("Hehe");

Console.WriteLine("显式接口示例");
person = new NewStudent(); ;
person.name = "Jason";
person.eat("Bread");
person.speak("Good Luck!");

NewStudent ns = new NewStudent();
//ns.name = "Lucy";         //报错,显式接口只能通过接口来调用

Console.ReadLine();
}


  运行结果

Main: 通过接口调用方法
Nick eat: apple
Nick say: Hello
Main: 通过类调用方法
Jessice eat: rice
Jessice say: Hehe
显式接口示例
Jason eat: Bread
Jason say: Good Luck!


  在显式实现接口时,NewStudent类中对应于IPerson接口的方法(或属性)名都有IPerson做前缀,而且方法(或属性)不允许有public、protected等访问修饰符。当一个类显式实现接口时,类中用于实现接口的方法只能通过接口

  来调用,而不能通过接口的实例来调用。

  接口与抽象类的对比

    接口与抽象类有相似之处,两者都可以定义一组属性和方法,都不能被创建实例,只能用作别的类的基类。但接口与抽象类有很大不同之处,如下:

    1、在抽象类中可以定义变量,而在接口中不可以

    2、在抽象类中可以定义构造函数,而接口中不可以

    3、在抽象类中可以定义非公共成员,如protected、private、internal等级的方法变量等,接口中只能定义public的成员

    4、抽象类中的非抽象方法可以有方法体,而接口中的方法只能有定义,不能有实现

    5、由于C#类只能单继承,所以一旦一个类继承了某个抽象类,那么就无法继承其他抽象类了。也就是说,抽象类的继承具有唯一性和排他性。而从接口继承却不存在这个问题。一个类继承某个接口,不影响这个类在继承其他接口

  综上,在接口中只能定义public访问级别的方法签名和属性签名,而抽象类除了不能生成类的实例外,其余的行为与普通类相同,能在普通类中定义的所有成员,都可以在抽象类中定义。抽象类中的方法允许定义实现代码,从而可以

  把派生类中的公共代码放在抽象类中,实现代码复用,减少派生类的编码量。

  接口与抽象类例子如下:

interface IPerson
{
void eat(object food);      //接口的方法
void speak(string text);    //接口的方法

string name                 //接口的属性
{
get;
set;
}
}

public abstract class Person
{
public void eat(object food)
{
Console.WriteLine(name + " eat: " + food.ToString());
}

public void speak(string text)
{
Console.WriteLine(name + " say: " + text);
}

private string _name;
public string name
{
get { return _name; }
set { _name = value; }
}
}

public class Child1:IPerson
{

public void eat(object food)
{
Console.WriteLine(name + " eat: " + food.ToString());
}

public void speak(string text)
{
Console.WriteLine(name + " say: " + text);
}

private string _name;
public string name
{
get
{
return _name;
}
set
{
_name = value;
}
}

public void Study()
{
Console.WriteLine(name + " study hard.....");
}
}

public class Adult1:IPerson
{
public void eat(object food)
{
Console.WriteLine(name + " eat: " + food.ToString());
}

public void speak(string text)
{
Console.WriteLine(name + " say: " + text);
}

private string _name;
public string name
{
get
{
return _name;
}
set
{
_name = value;
}
}

public void Work()
{
Console.WriteLine(name + " work hard....");
}
}

public class Child2:Person
{
public void Study()
{
Console.WriteLine(name + " study hard....");
}
}

public class Adult2:Person
{
public void Work()
{
Console.WriteLine(name + " work hard...");
}
}

static void Main(string[] args)
{
Child1 child1 = new Child1();
Child2 child2 = new Child2();
Adult1 adult1 = new Adult1();
Adult2 adult2 = new Adult2();

child1.name = "Jack";
child1.eat("apple");
child1.speak("hello");
child1.Study();

adult1.name = "Nick";
adult1.eat("apple");
adult1.speak("hello");
adult1.Work();

child2.name = "Lucy";
child2.eat("rice");
child2.speak("hello");
child2.Study();

adult2.name = "Lily";
adult2.eat("banana");
adult2.speak("hello");
adult2.Work();
}


  运行结果

Jack eat: apple
Jack say: hello
Jack study hard.....
Nick eat: apple
Nick say: hello
Nick work hard....
Lucy eat: rice
Lucy say: hello
Lucy study hard....
Lily eat: banana
Lily say: hello
Lily work hard...


  从Child1和Adult1类的实现代码来看,两个类都继承自IPerson,为了实现接口中定义的方法,相同的代码在两个类中写了两遍。

  从Person、Child2和Adult2类代码可以看出,在Person中实现了方法和属性,不用再派生类中重复实现,实现了代码的复用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: