在代码中实现接口

时间:2009-06-22 15:27:59

标签: c# interface

我一直在摸不着头几天,我仍然无法理解如何实现这个界面。

这是我的代码:

namespace ConsoleApplication32 {
public static class ScanAndSerialize
{

    public static void Serialize()
    {

        List<string> dirs = FileHelper.GetFilesRecursive("s:\\");
        List<string> dirFiles = new List<string>();
        foreach (string p in dirs)
        {
            string path = p;
            string lastAccessTime = File.GetLastAccessTime(path).ToString();
            bool DirFile = File.Exists(path);
            DateTime lastWriteTime = File.GetLastWriteTime(p);
            //dirFiles.Add(p + " , " + lastAccessTime.ToString() + " , " + DirFile.ToString() + " , " + lastWriteTime.ToString());
            dirFiles.Add(p);
            dirFiles.Add(lastAccessTime);
            dirFiles.Add(DirFile.ToString());
            dirFiles.Add(lastWriteTime.ToString());
            dirFiles.Add(Environment.NewLine);

        }


        XmlSerializer SerializeObj = new XmlSerializer(dirFiles.GetType());
        string sDay = DateTime.Now.ToString("MMdd");
        string fileName = string.Format(@"s:\project\{0}_file.xml", sDay);
        TextWriter WriteFileStream = new StreamWriter(fileName);

        SerializeObj.Serialize(WriteFileStream, dirFiles);
        WriteFileStream.Close();


    }

    static class FileHelper
    {
        public static List<string> GetFilesRecursive(string b)
        {
            // 1.
            // Store results in the file results list.
            List<string> result = new List<string>();

            // 2.
            // Store a stack of our directories.
            Stack<string> stack = new Stack<string>();

            // 3.
            // Add initial directory.
            stack.Push(b);

            // 4.
            // Continue while there are directories to process
            while (stack.Count > 0)
            {
                // A.
                // Get top directory
                string dir = stack.Pop();

                try
                {
                    // B
                    // Add all files at this directory to the result List.
                    result.AddRange(Directory.GetFiles(dir, "*.*"));

                    // C
                    // Add all directories at this directory.
                    foreach (string dn in Directory.GetDirectories(dir))
                    {
                        stack.Push(dn);
                    }
                }
                catch
                {
                    // D
                    // Could not open the directory
                }
            }
            return result;
        }
    }



    public class MyInterface: IValidationRowSet
    {

        public int RowNumber { get; set; }

        public string RowAsString { get; set; }
        public IValidationRowSet MatchedRow { get; set; }
        public string FriendlyNameLabel { get; set; }
        public string KeyFieldLabel { get; set; }
        IList<string> lst = new List<string>();
        public string SourceWorksheetName { get; set; }
        public string SourceRangeName { get; set; }
        //public string SourceRangeName { get; set; }
        public bool bReported { get; set; }

        public int FieldCount { get { return lst.Count; } }
        public string FieldData(int id)
        {
            if (id <= lst.Count)
                return lst[id];
            else
                return null;
        }
        public string ValidationMessage { get; set; }




    }

以下是对界面的解释(仍然在我的头上划过头)

namespace Validation {
/// <summary>
/// Implement this interface if you want the engine to callback when it finds exception
/// messages.  You will pass a reference to you class to the validation engine, and 
/// it will call "PostValidationMessage" for each exception example, including the message,
/// the entire row set of data (vr), and the id of the field that created the exception.
/// </summary>
public interface IValidationReporter
{
/// <param name="sMsg"></param>
/// <param name="vr"></param>
/// <param name="id"></param>
    void PostValidationMessage(string sMsg, IValidationRowSet vr, int id);
}


/// <summary>
/// Implement this interface in order to use the validation engine.
/// The validation engine takes 2 IList<IValidationRowSet> objects and compares them.
/// A class that implements this interface will contain an entire row of data that you'll
/// want to compare.
/// </summary>
public interface IValidationRowSet
{

    /// <summary>
    /// should return an int of the number of fields in this row
    /// </summary>
    int FieldCount { get; }

    /// <summary>
    /// should return an int of the row number that this row is in the set
    /// usually set when the data is assembled
    /// </summary>
    int RowNumber { get; set; }

    /// <summary>
    /// this is a function that should return the field data for this row at zero-indexed location "id"
    /// ex: if the row contains this data: smith|fred|2126782524|fred@smith.com|
    /// a call on this method of FieldData(2) will return the phone number 2126782524
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    string FieldData(int id);

    /// <summary>
    /// this will be modified by the validation process
    /// </summary>
    string ValidationMessage { get; set; }

    /// <summary>
    /// this will be modified by the validation process
    /// </summary>
    IValidationRowSet MatchedRow { get; set; }

    /// <summary>
    /// returns a string that uniquely identifies this row
    /// ex: if the row contains this data: smith|fred|2126782524|fred@smith.com|
    /// so for this example, the unique identifier could be the email address fred@smith.com
    /// </summary>
    string KeyFieldLabel { get; set; }

    /// <summary>
    /// returns a string with the "friendly" name of this row
    /// ex: if the row contains this data: smith|fred|2126782524|fred@smith.com|
    /// so for this example, FriendlyNameLabel could be the name, such as "Fred Smith"
    /// </summary>
    string FriendlyNameLabel { get; set; }

    /// <summary>
    /// returns all fields in the row as pipe delimited
    /// ex: 1,234.23|Fred Smith|Fred@smith.com|
    /// </summary>
    string RowAsString { get; set; }


    /// <summary>
    /// if this is an excel file comparison, this should return the name 
    /// of the worksheet from whence this data came
    /// </summary>
    string SourceWorksheetName { get; set; }


    /// <summary>
    /// if this is an excel file comparison, this should return the name 
    /// of the worksheet range from whence this data came
    /// </summary>
    string SourceRangeName { get; set; }

    /// <summary>
    /// this will be modified by the validation process
    /// </summary>
    bool bReported { get; set; }
}
}

我已阅读有关Interfaces的NUMEROUS文章/书籍/论坛帖子。这个概念对我来说就像是一个黑洞......我正处于一个我必须实现这个目标的项目中。任何人都知道你是如何实现这一点的?顺便说一句 - 我是一个完整的新手程序员...不到2个月的经验......所以请不要因为我的绿色而惩罚我。

提前致谢。

7 个答案:

答案 0 :(得分:3)

将接口视为原型或要填充的拼图的模板 - 将它们视为空白区域和线条放置的位置。你必须将接口派生成具体的类 - 漂亮的图片拼图。

让我保存这个,我会举一个例子。

interface IFoo
{
    bool DoFoo(int number);
}

class Foo : IFoo
{
    public bool DoFoo(int number) {
         return (number++ >= 0); 
    }
}

class Foo2 : IFoo
{
    public bool DoFoo(int number) {
         return (number-- >= 0); 
    }
}

现在我有了,我可以做这样的事情。

IFoo foo;

if (!value)
    foo = new Foo();
else
    foo = new Foo2();

bool value2 = foo.DoFoo(27);

注意,我无法通过接口执行此操作:

// WRONG
Foo2 foo2 = new Foo();

这基本上总结了界面的作用及其工作原理。您现在的工作是实现接口的具体实现。

答案 1 :(得分:2)

您可以想象界面就像您的班级必须回答的问题列表。这样,您就可以创建许多类,这些类将以不同的方式回答这些问题。

但对于提出问题的人(这是一个ValidationReporter),只有获得答案才是重要的,而不是谁会回答。

一个。您需要告诉编译器您的类实现了接口

// my class implements the interface
public class MyValidationRowSet : IValidationRowSet

湾您需要实现每个接口方法。这意味着您需要确保每个方法实际执行某些操作。在Visual Studio中,您可以通过右键单击上面一行中的界面并从上下文菜单中选择“实现界面”来获得帮助。这将创建方法存根(您可以填写的空方法)。

public class MyValidationRowSet : IValidationRowSet
{
     public int FieldCount
     { 
         get
         {
             // return something
         }
     }

    // you will need to implement each method from your
    // interface in order to compile successfully
}

我可以从您的代码(public class MyInterface: IValidationRowSet)中看到您没有实现任何方法 - 您将它们全部留空。编译器不会让你运行程序,直到它确定你的方法返回正确的结果。

℃。基本上就是这样。一旦你超越了a。,在你在该接口中实现所有方法之前,编译器将不允许你运行程序。完成后,您可以创建一个新的实例,可以“给出答案”:

// create a new instance of your class
MyValidationRowSet instance = new MyValidationRowSet();

答案 2 :(得分:1)

作为一名新开发人员,我发现了将接口视为模板的最佳方式,该模板包含有关类的所有公共信息(属性,方法等),作为需要为类创建的内容的列表实现它来完成这些方法所需的工作等。

现在应该有一大群人会比我更好地解释这一点,并纠正我的错误,并希望以一种你(并希望我)可以理解的方式解释与文章/书籍/帖子不同的界面:)

答案 3 :(得分:1)

作为取得进展的指南,我建议对所有方法进行硬编码以返回虚拟数据,或者抛出一个未实现的异常。

例如:

RowNumber // Always returns 1
RowAsString // return "FirstName,LastName,PhoneNumber"
MatchedRow  // throw exception
FriendlyNameLabel // return "MyFriendlyRow"
KeyFieldLabel// return "MyKeyField"
SourceWorksheetName // return "DefaultWorksheet"
SourceRangeName  // return "DefaultRange"
bReported // return true;
FieldCount // return 3 (to match the number of fields indicated in RowAsString
FieldData // simple switch/case: 0=>FirstName, 1=>lastName, 2=>PhoneNumber
ValidationMessage // return "Data not validated"

这应该使您的代码编译...甚至可能运行,然后您可以开始调试它以弄清楚应该如何使用它。一点一点地删除“虚拟”实现并输入“真实”代码。

旁注:您的初始代码块“ScanAndSerialize”似乎与IValidationRowSet无关。我有什么联系吗?

答案 4 :(得分:0)

如果您使用的是visual studio,只需编写“public class foo:IValidationRowSet”即可。然后单击左键单击foo,然后按+ Alt + f10,向下,输入。这将生成接口实现的存根。

并且不要将类命名为“MyInterface”,这令人困惑。它是接口的实现,而不是接口本身。 :)

答案 5 :(得分:0)

很难说出你的思想在哪些方面存在问题。

接口是一个抽象概念。不仅在字面上而且在本质上,抽象类和接口无法实例化。接口比抽象类更抽象,因为它不能包含任何可执行代码。它在接口的使用者和实现接口的类之间建立了一个契约。

现在,如果你听到多态性并且开始摸不着头脑,那么界面将是一个难题。接口是在应用程序中引入多态的常用方法之一。您可以拥有IValidationReporter和IValidationRowSet的许多实现。由于您抽象了合同,任何可以使用这些抽象的代码都可以保持不变,即使在您切换这些合同的实现的情况下也是如此。

您的代码实现了其中一个接口而不是另一个接口。另请注意,静态构造不能在契约(接口)中表示

答案 6 :(得分:0)

不完全确定你在问什么,但这里有一些观察:

public class MyInterface:IValidationRowSet {...}

MyInterface不是您班级的“智能”名称,因为它不是一个界面。 它是接口的实际实现。我建议改为ValidationRowSetImpl,或MyRowSet,或类似的。

另外,你有

IList<string> lst = new List<string>();

停留在接口实现的中间。 它应该被明确地称为“私人”,并且出于良好组织的原因,应该在您的班级底层。接口中的所有方法应该在一起,与接口的顺序相同。使用的所有私人日期应低于该日期。