ASP.NET:不熟悉接口

时间:2009-02-17 18:31:19

标签: asp.net vb.net interface

我正在使用各种对象在ASP.NET / VB.NET中构建一个体面的应用程序...我之前从未使用过接口,当我向他提到这个时,一位程序员也不愿意这样做。任何人都可以快速概述一下它们的使用方法,它们的用途以及我使用它们的原因吗?也许我不需要在这个项目中使用它们,但是如果它们有所帮助,我肯定会喜欢尝试。

非常感谢!

6 个答案:

答案 0 :(得分:7)

一旦你“获得”接口,OOP真正落到了位置。简单地说,一个接口定义了一组公共方法签名,你创建了一个实现这些方法的类。这允许您为实现特定接口的任何类(即具有相同方法的类)概括函数,即使这些类不一定相互下降。

Module Module1

    Interface ILifeform
        ReadOnly Property Name() As String
        Sub Speak()
        Sub Eat()
    End Interface

    Class Dog
        Implements ILifeform

        Public ReadOnly Property Name() As String Implements ILifeform.Name
            Get
                Return "Doggy!"
            End Get
        End Property

        Public Sub Speak() Implements ILifeform.Speak
            Console.WriteLine("Woof!")
        End Sub

        Public Sub Eat() Implements ILifeform.Eat
            Console.WriteLine("Yum, doggy biscuits!")
        End Sub
    End Class

    Class Ninja
        Implements ILifeform

        Public ReadOnly Property Name() As String Implements ILifeform.Name
            Get
                Return "Ninja!!"
            End Get
        End Property

        Public Sub Speak() Implements ILifeform.Speak
            Console.WriteLine("Ninjas are silent, deadly killers")
        End Sub

        Public Sub Eat() Implements ILifeform.Eat
            Console.WriteLine("Ninjas don't eat, they wail on guitars and kick ass")
        End Sub
    End Class

    Class Monkey
        Implements ILifeform


        Public ReadOnly Property Name() As String Implements ILifeform.Name
            Get
                Return "Monkey!!!"
            End Get
        End Property

        Public Sub Speak() Implements ILifeform.Speak
            Console.WriteLine("Ook ook")
        End Sub

        Public Sub Eat() Implements ILifeform.Eat
            Console.WriteLine("Bananas!")
        End Sub
    End Class


    Sub Main()
        Dim lifeforms As ILifeform() = New ILifeform() {New Dog(), New Ninja(), New Monkey()}
        For Each x As ILifeform In lifeforms
            HandleLifeform(x)
        Next

        Console.ReadKey(True)
    End Sub

    Sub HandleLifeform(ByVal x As ILifeform)
        Console.WriteLine("Handling lifeform '{0}'", x.Name)
        x.Speak()
        x.Eat()
        Console.WriteLine()
    End Sub
End Module

上面没有一个类彼此相继,但是我的HandleLifeform方法被推广到对所有类进行操作 - 或者实际上是任何实现ILifeform接口的类。

答案 1 :(得分:3)

由于已经涵盖了基础知识,让我们继续实际的例子。

假设我要有一个存储字符串键和Person对象的Dictionary,我将把这个字典(实际上是对它的引用)传递给我的一些方法。

现在,我的接收方法看起来像

Imports System.Collections.Generic
Public Sub DoSomething(ByVal myDict As Dictionary(Of String, Person))
    ' Do something with myDict here
End Sub

正确?

但是,如果有人发明了一些新的高性能字典课呢?我必须转而将每个对Dictionary的引用更改为FastDictionary!

但是,如果我首先编码到界面,我就不会遇到这个问题:

Imports System.Collections.Generic
Public Sub DoSomething(ByVal myDict As IDictionary(Of String, Person))
    ' Do something with myDict here
End Sub

现在它需要任何字典!

答案 2 :(得分:2)

接口基本上允许您定义类型的合同而不指定其实现。

这个想法是,如果您知道某个给定类型实现了某个接口,那么它可以保证某些方法和属性是该类型的成员。

所以实现以下接口的任何类型:

Interface ISpinnable
    Sub Spin()
End Interface

必须实施Spin方法。但是实现ISpinnable的这种类型的调用者不关心如何实现它,它只关心该方法是否存在。这是一个实现ISpinnable的类型:

Class Top Implements ISpinnable
    Sub Spin()
        ' do spinning stuff
    End Sub
End Class

这样做的好处是,您可以创建类型为ISpinner的方法参数,并允许这些方法的调用者只要实现接口就将任何类型传递给您。您的方法不再与调用者正在使用的具体类型紧密耦合。

答案 3 :(得分:1)

接口是没有实现的合同。它允许您定义类型的外观,而不指示该类型的实现是什么。

这允许您拥有一个适合您特定需求的接口的各种实现。

一个很好的例子是IComparer(Of T)接口。你可以有一个实现来比较两个基于哪个更大的项,然后另一个将返回一个更小的值。

然后,您可以将一个或另一个传递给Array类上的静态Sort方法,以分别按升序或降序对项目进行排序。

答案 4 :(得分:1)

接口可能有用的一点是浏览不同类型但共享相同接口的对象数组。 不能说对于VB,但是在C#中你可以使用方便的“is”运算符来确定对象的类型是否实现了给定的接口,并且通过强制转换访问该接口的方法是安全的。对不起C#,但我会尝试在=))

中添加一些注释
//we declare 3 different interfaces each requiring to implement one method
                    interface IProgrammer
                    {
                        void WriteCode();
                    }

                    interface ITester
                    {
                         void FindBugs();
                    }

                    interface IWorker
                    {
                         void StartShift();
                    }

        // each programmer will be able to start his shift and write code
                    class Programmer : IWorker, IProgrammer
                    {

                        public void StartShift()
                        {
                          // ...
                        }

                        public void WriteCode()
                        {
                          // ...
                        }

                    }

        // each tester will be able to start his shift and find bugs

                    class Tester : IWorker, ITester
                    {
                        public void StartShift()
                        {
                            // ...
                        }

                        public void FindBugs()
                        {
                            // ...
                        }
                    }

            //then in code you can rely on objects implementing the interface to 
            // be able to do tasks interface requires to do
                    static void Main()
                    {
                        IWorker[] workers = new IWorker[3];
                        workers[0] = new Programmer();
                        workers[1] = new Tester();
                        workers[2] = new Tester();

       // now we can browse through array of different workers because they all share
       // the IWorker interface
                    foreach(IWorker worker in workers)
                    {
                        // All IWorkers can StartShift so we access its methods without casts
                        worker.StartShift();
                        if(worker is IProgrammer)
                        {
                            // Since that worker also implements IProgrammer
                            // we cast worker as IProgrammer and access IProgrammer method(s)
                            (worker as IProgrammer).WriteCode();
                        }
                        if(worker is ITester)
                        {
                            // Same,
                            // we cast worker as ITester and access ITester method(s)
                            // handy! =)
                             (worker as ITester).FindBugs();
                        }
                    }

答案 5 :(得分:1)

一个典型的例子是数据层,您可以使用它来支持多种数据库格式。在ORMappers进入主流编程之前,这实际上非常有用。

您的界面只是告诉您对象具有哪种类型的方法和属性,然后对象本身必须实现这些方法。

IMyDatabase myDb;

switch case myDbFormat {
     case "mysql":
        myDb = new MyDbMySql();
        break;
     case "mssql" :
        myDb = new MyDbMsSql();
        break;    
}

myDb.SaveToDatabase(some data)

当然,myDb类必须实现ImyDatabase接口。我假设你可以看到这是多么有用:)。