`

C#接口和抽象类:Interface、abstract

阅读更多

 

转自:http://www.soaspx.com/dotnet/csharp/csharp_20091030_1359.html

 

一、接口

接口是C#中很常见的工具,概念什么的就不说了,这里讲几个值得注意的小地方:

1、接口内部只能有函数、属性和事件的声明:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->interface IParent
{
    
void
 Show();
    
string
 Type     //--属性的声明
    {
        
get
;           //-- get; 不能为get{};或是:get();

        
set;
    }
    
event
 AddChildren Add;
}

在接口中声明的成员都不需要访问修饰符(public,private等),因为接口成员的权限默认都是public,另外值得注意的是接口中之所以能够声明事件是因为事件就是委托的特殊属性。

接口不能是静态的,接口成员也只能声明为实例成员不能声明为静态成员,如下声明就是错误的:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->static interface IParent
    {
        
static void Show();
        
string Type
        {
            
get;
            
set;
        }
        
event AddChildren Add;
    }

你会得到提示:

错误 1 修饰符“static”对该项无效 C:\Documents and Settings\HMD\桌面\CLR_Excise\CLR_Excise\Lib.cs 10 22 CLR_Excise

原因是如果接口是静态的就无法被继承,静态成员也无法被接口直接访问(因为接口中的成员都还没有实体只是声明)所以定义在接口中无意义。

 

 

2、接口支持部分声明:

上面的接口实际上可以在一个命名空间里声明为3部分:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->partial interface IParent
    {
        
void Show();
    }

    
partial interface IParent
    {
        
string Type
        {
            
get;
            
set;
        }
    }

    
partial interface IParent
    {
        
event AddChildren Add;
    }

上面这种部分接口的声明方式和声明为一个接口的效果完全相同,若要了解部分关键字partial请查看:C#里partial关键字的作用(转摘)

 

3、接口的实现:

接口成员的实现方式分为两种:

<1>隐式实现:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->class ChildrenA : IParent
        {

            
#region IParent 成员

            
public void Show()
            {
                
throw new NotImplementedException();
            }


            
public string Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }

            
public event AddChildren Add;

            
#endregion
        }

 在类中隐式声明的接口成员都必须是public访问权限

 

(2)如果有一个类C实现了两个接口IA、IB且IA、IB都有同名函数void Display();那么可以在C中隐式实现Display,这样即实现了IA的Dislpay也实现了IB的Display

例如:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
        
public interface IParent
        {
            
void Show();
            
string Type
            {
                
get;
                
set;
            }
            
event AddChildren Add;
        }

        
public interface IFather
        {
            
void Show();
            
string Type
            {
                
get;
                
set;
            }
            
event AddChildren Add;
        }


        
public class ChildrenA : IParent, IFather
        {


            
#region IParent,IFather 成员

            
public void Show()
            {
                
throw new NotImplementedException();
            }

            
public string Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }

            
public event AddChildren Add;

            
#endregion
        }

 

在上面类CA中将IParent和IFather的同名成员都用隐式实现接口成员的方式一次性实现了。

 

(3)隐式实现接口属性的时候可以扩充接口属性的访问器,例如:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public interface IParent
        {
            
string Type
            {
                
get;
            }
        }

        
public class CParent : IParent
        {

            
#region IParent 成员


            
public string Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }


            
#endregion
        }

本来接口属性Type只有get访问器,但是实现接口的类CParent扩充了接口属性Type即定义了get访问器也定义了set访问器,这在隐式实现接口属性的时候是允许的,但是在显式实现接口属性的时候必须严格按照接口定义的格式来!

 

<2>显式声明接口:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->        class ChildrenA : IParent
        {

            
void IParent.Show()
            {
                
throw new NotImplementedException();
            }


            
string IParent.Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }

            
event AddChildren IParent.Add
            {
                add { 
throw new NotImplementedException(); }
                remove { 
throw new NotImplementedException(); }
            }
        }

显式实现接口不能设置实现成员的访问权限(因为显式声明成员的权限就是其对应接口成员的权限,当然就是public)

此外显式实现接口需要注意以下几点:

(1)显式实现接口,那么实现的接口成员只能由接口调用,因为显式实现的接口成员对于实现类来说是不可见的。

(2)显式实现接事件的时候要注意,只能显示实现事件的定义,例如显式实现IParent.Add事件的时候,用的显式实现事件:

event AddChildren IParent.Add
{
  add { throw new NotImplementedException(); }
  remove { throw new NotImplementedException(); }
}

如果用隐式实现事件就会报错:

event AddChildren IParent.Add
提示:错误 1 事件的显式接口实现必须使用事件访问器语法 C:\Documents and Settings\HMD\桌面\CLR_Excise\CLR_Excise\Lib.cs 45 38 CLR_Excise

 

(3)上面隐式实现接口(3)中的例子没有区分IParent、IFather同名成员的实现,而是在继承类CA中由隐式实现方式统一实现。下面举例说明如何将IParent、IFather的同名成员分别实现:

还是有一个类C实现了两个接口IA、IB且IA、IB都有同名函数void Display();,这次为了区分IA,IB同名成员Dispaly函数的实现,可以在CA中将一个接口的Display函数用显式方式实现,这说明在实现接口的时候可以将其中一个接口的同名成员用显式方式实现,以区分同名成员的实现

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public delegate void AddChildren();

        
interface IParent
        {
            
void Show();
            
string Type
            {
                
get;
                
set;
            }
            
event AddChildren Add;
        }

        
interface IFather
        {
            
void Show();
            
string Type
            {
                
get;
                
set;
            }
            
event AddChildren Add;
        }


        
class ChildrenA : IParent, IFather
        {


            
#region IParent 成员

            
public void Show()
            {
                
throw new NotImplementedException();
            }

            
public string Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }

            
public event AddChildren Add;

            
#endregion

            
#region IFather 成员

            
void IFather.Show()
            {
                
throw new NotImplementedException();
            }

            
string IFather.Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }

            
event AddChildren IFather.Add
            {
                add { 
throw new NotImplementedException(); }
                remove { 
throw new NotImplementedException(); }
            }

            
#endregion
        }

现在就将IParent和IFather接口的同名成员分开实现了,其中将IFather接口的同名成员用显式方式声明以区分IParent接口的实现。事实上可以将IParent和IFather的成员都以显式方式实现,不过这样实现类CA就不能访问到IParent和IFather的成员了,只有用IParent和IFather来访问它们各自的成员。

 

 (4)如果实现类继承了具有同名成员的抽象类,那么加上override关键字后即实现了抽象类也实现了接口

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public delegate void AddChildren();

        
interface IParent
        {
            
void Show();
            
string Type
            {
                
get;
                
set;
            }
            
event AddChildren Add;
        }

        
abstract class AParent
        {
            
public abstract void Show();
            
public abstract string Type
            {
                
get;
                
set;
            }
            
public abstract event AddChildren Add;
        }

        
class ChildrenA :AParent, IParent
        {


            
#region AParent、IParent 成员

            
public override void Show()
            {
                
throw new NotImplementedException();
            }

            
public override string Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }

            
public override event AddChildren Add;

            
#endregion

        }

 

 

二、抽象类

抽象类是C#里面用的相对较少的工具,不过在有些场合他比接口更有用,抽象类的作用与接口类似就是声明个框架,让继承类照着这个框架去实现,不过抽象类允许对已经确定的部分先进行实现,继承类要做的就是实现没有确定的成员(抽象成员)

abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。

在使用抽象类的时候需要注意:

(1)抽象类和接口一样是个框架,本身不能被实例化,只能通过继承类将其实例化。

(2)抽象类不能使用sealed和static关键字,因为使用sealed关键字表示类不能被继承,而静态类也不能被继承,抽象类不被继承是完全没有意义的。

(3)实现抽象类的类必须实现抽象类的所有抽象成员(标记了abstract的成员):

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public abstract class AParent
        {
            
public abstract void Show();
            
public abstract string Type
            {
                
get;
                
set;
            }
            
public abstract event AddChildren Add;
            
public int tInt
            {
                get
                {
                    return 1;
                }
            }

        }

        
public class Parent : AParent
        {

            
public override void Show()
            {
                
throw new NotImplementedException();
            }

            
public override string Type
            {
                
get
                {
                    
throw new NotImplementedException();
                }
                
set
                {
                    
throw new NotImplementedException();
                }
            }

            
public override event AddChildren Add;
        }

Parent类实现了AParent的所有抽象成员,但是并没有实现AParent的非抽象成员public int tInt

(4)抽象成员都是虚成员(virtual),这一点上面的代码中可以看到,实现抽象类的成员都使用了关键字override(实现抽象成员必须要用override)表示重写抽象类的抽象成员

(5)抽象成员不能标记为static(原因同接口)、virtual,且抽象成员不能是private的(原因就是private成员无法被继承)。

(6)抽象类的抽象成员可以重写(override)或隐藏(new)基类成员:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->abstract class ACA
        {
            
public abstract void Call();
        }

        
abstract class ACB : ACA
        {
            
public override abstract void Call();
        }

如上所示ACB的抽象成员就重写了父类ACA的抽象成员

(7)抽象类也支持部分定义,例如可以将(3)中的AParent分成3部分定义,其效果和定义成一个相同:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public abstract partial class AParent
        {
            
public abstract void Show();
            
public int tInt
            {
                
get
                {
                    
return 1;
                }
            }
        }
        
public abstract partial class AParent
        {
            
public abstract string Type
            {
                
get;
                
set;
            }
        }
        
public abstract partial class AParent
        {
            
public abstract event AddChildren Add;
        }
分享到:
评论

相关推荐

    1.5:接口和抽象类的区别.pdf

    4.实现抽象类和接口的类必须实现其中的所有方法。 抽象类中可以有非抽象方法。接口中则不能有实现方法。如果接口或者抽象类的子类不想实现则继续携程一个抽象方法 5.接口中定义的变量默认是public static final ...

    override abstract virtual interface比较

    Override 关键字用于重写父类中的虚拟方法,Abstract 关键字用于声明抽象类和抽象方法,Virtual 关键字用于声明虚拟方法,而 Interface 关键字用于声明接口。只有正确地使用这些关键字,才能编写出高质量的 C# 程序...

    C#入门经典(9章),学好C#你绝对需要!!!

    C#入门经典(9章),学好C#你绝对需要!! 本章主要内容: 1. 类的定义 2. 接口的定义 3. System.Object 类 ...本章主要介绍了C#中的类和接口的定义、继承和实现,System.Object类的成员和构造函数的使用。

    c#中抽象类、接口的使用例子

    一个完整的例子: using System; using System.Collections.Generic... interface IAnimal //顶层接口 { void eating(); //接口中声明的方法,这里不可以用static,abstract修饰 } abstract class Bird :IAnima

    C#面向对象编程封装习题.pdf

    除了封装对象的状态和行为外,我们还可以使用接口(Interface)和抽象类(Abstract Class)来实现封装。接口是指一个抽象的类,它定义了一组方法和事件的签名,但不提供实现。抽象类是指一个 partial实现的类,它...

    C#程序设计期末试卷.pdf

    例如,abstract class BaseClass {}是一个抽象类。 10. 接口:接口是指包含抽象方法的集合,必须被实现。例如,interface IMyInterface { void MethodA(); }是一个接口。 11. 构造函数的说法:一个类可以有多个...

    某211大学 .net 教学课件PPT 第四章 C#面向对象的编程.ppt

    本资源是关于C#面向对象编程的教学课件,主要介绍了C#面向对象编程的基础知识,包括重载、接口、继承、抽象类、密封类、分部类等概念。下面是对这些知识点的详细解释: 一、重载(Overload) 在C#中,重载是指在同...

    c# 接口interface基础入门小例子

    代码如下: ///  /// interface /// 与抽象类的区别: /// 1,abstract可以有具体方法和抽象方法(必须有一个抽象方法),interface没有方法实现 /// 2,abstract可以有构造函数和析构函数,接口不行 /// 3,一...

    C#-程序设计教程第6章.ppt

    本节课讨论了面向对象程序设计中的一些高级应用,包括继承、访问控制符、多态性、密封类、抽象类和接口。 1. 继承(Inheritance) 继承是面向对象程序设计中的一种重要机制,它使得程序员可以使用已有类的成分来...

    2023年C#面试题中常见比较.doc

    在C#中,接口(interface)和抽象类(abstract class)都是用于定义蓝图的语言结构,但它们有着不同的设计目标和使用场景。接口是一种特殊的抽象类,它定义了一组方法签名,但不提供任何实现。抽象类则可以提供部分...

    01:详解C#中的反射.pdf

    反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个...

    【ASP.NET编程知识】常用C#关键字详解教程(比较全面).docx

    Abstract关键字可以和类、方法、属性、索引器及事件一起使用,用于指示某个类只能是其他类的基类。例如: public abstract class MyClass { } 19. Internal关键字 Internal关键字是类型和类型成员的访问修饰符,...

    C#常用关键字及含义.doc

    * interface:将一个声明指定为接口类型,即实现类或构造必须遵循的合同。 * new:用于调用构造器的操作符,同时,也是一个修饰符,用来隐藏而非重载拥有同样签名的一个继承方法。 * override:一个修饰符,说明一个...

    从实例谈面向对象编程、工厂模式和重构

    不过不用着急,因为接口这个利器你还没有用上 (虽然你也可以用抽象类,但在 C#里只支持类的单继承)。 虽然视频和音频格式不同,别忘了,他们都是媒体中的一种,很多时候,他们有许多相似的功能,比如播 放。根据...

    net学习笔记及其他代码应用

    接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类...

    二十三种设计模式【PDF版】

    和智慧,让你能够真正掌握接口或抽象类的应用,从而在原来的 Java 语言基础上跃进一步,更重要的是,GoF 的设计模式反复 向你强调一个宗旨:要让你的程序尽可能的可重用。 这其实在向一个极限挑战:软件需求变幻...

    亮剑.NET深入体验与实战精要2

    2.5 abstract class与interface 91 2.6 公共变量与属性的区别 93 2.7 参数修饰符params、out和ref的区别 96 2.8 值类型和引用类型的区别 100 2.9 结构与类的区别 103 2.10 Dispose()和Close()、Finalize()的 区别 ...

    亮剑.NET深入体验与实战精要3

    2.5 abstract class与interface 91 2.6 公共变量与属性的区别 93 2.7 参数修饰符params、out和ref的区别 96 2.8 值类型和引用类型的区别 100 2.9 结构与类的区别 103 2.10 Dispose()和Close()、Finalize()的 区别 ...

Global site tag (gtag.js) - Google Analytics