如何实现这个Base / Derived类结构?

时间:2011-09-21 10:00:39

标签: c# oop

我正在编写一个C#应用程序,它读取语言X的源代码文件,并使用源文件中出现的类,方法等填充数据结构。

之后,使用我刚刚填充的这个数据结构,我可以调用这三个函数中的任何一个:

GenerateCS()
GenerateJava()
GenerateCPP()

基本上,它将语言X移植到这三种语言中的任何一种。

我的问题是,我如何构造这样的结构,使得我有一个类GenerateCode作为基类,另一个生成函数从中派生出来? 我想每种语言的特定语法细节必须驻留在派生类本身中,但是我可以将哪些内容抽象到超类?

2 个答案:

答案 0 :(得分:1)

怎么样:

public enum Language
{
    CS,
    Java,
    CPP
}

public class CS: BaseClass { }
public class Java: BaseClass { }
public class Cpp: BaseClass { }

public class BaseClass
{
    public abstract BaseClass ConvertTo(Language lang);
}

public class BaseClass
{
    public abstract FromClass(BaseClass class, Language lang);
}

答案 1 :(得分:1)

我建议您从这样的结构开始:

public class MetaCode
{
    private IList<Fields> fields;
    private IList<Properties> properties;
    private IList<Methods> methods;

    public IList<Fields> Fields
    {
        get { return this.fields; }
    }

    public IList<Properties> Properties
    {
        get { return this.properties; }
    }


    public IList<Methods> Methods
    {
        get { return this.methods; }
    }

    // etc...
}

public interface ISourceReader
{
    MetaCode ReadCode(string sourceCode);
}

public interface ISourceWriter
{
    string WriteCode(MetaCode metaCode);
}

public class CodeConverter
{
    private ISourceReader reader;
    private ISourceWriter writer;

    public CodeConverter(ISourceReader reader, ISourceWriter writer)
    {
        this.reader = reader;
        this.writer = writer;
    }

    public string Convert(string sourceCode)
    {
        MetaCode metaCode = this.reader.ReadCode(sourceCode);
        return this.writer.WriteCode(metaCode);
    }
}

这只是伪代码,但您可以使接口遵循.NET框架中经常出现的StreamReader / StreamWriter模式。

接口允许整齐的扩展点,您可以在其中向应用程序添加新的源和目标编程语言。这种方法最好的事情是CodeConverter类对存在的不同编程语言一无所知。可以添加或删除新的,不需要更改。其他人甚至可以创建新的语言读者/编写者并使用它们而无需触及您的代码/编译程序集。

老实说,考虑到这一点,我不认为有很多功能可以抽象到基类。每种语言的细节都是如此具体,以至于基类很难正确完成。在任何情况下,我总是建议从接口开始,因为无论编程语言有多么模糊/不同,你总是可以创建一个实现。

也许你可以创建几个“辅助”基类,它们包含一些抽象功能,用于编程语言的不同通用样式:

public abstract class CLikeSourceReader : ISourceReader
{
    public MetaCode ReadCode(string sourceCode)
    {
        // etc..
    }

    // etc..
}

public abstract class VisualBasicLikeSourceReader : ISourceReader
{
    public MetaCode ReadCode(string sourceCode)
    {
        // etc..
    }

    // etc..
}

public abstract class AssemblyLanguageLikeSourceReader : ISourceReader
{
    public MetaCode ReadCode(string sourceCode)
    {
        // etc..
    }

    // etc..
}

这样,在添加新语言时,您可以选择从这些预先存在的基类之一继承,如果它们都不合适,可以选择回退到接口。