2010-04-26 354 views
2

可能重复:
What is an abstract class ?为什么需要抽象类?

1.什么是创建一个不能被实例化一个类的呢?

通常用作基类或接口(某些语言具有单独的接口构造,有些则不) - 它不知道实现(即由子类/实现类提供)

2.为什么会有人想要这样的班级?

For abstraction and re-use 

3.什么是抽象类成为必要的情况?任何人都可以用一个例子来简要介绍一下吗?

+0

这是一个愚蠢的愚蠢。 – slugster 2010-04-26 12:31:14

回答

5

抽象类允许您编写一段通用的代码,将特定决策推迟到派生类,从而减少代码重复。

+0

@OtávioDécio:当基类不能为方法提供有意义的默认实现时必需? – bala3569 2010-04-26 12:26:34

+1

@ bala3569:抽象基类*可以为方法(或大部分方法)提供有意义的默认实现。看到我的答案。 – 2010-04-26 12:28:57

4

当您创建一个继承树时,您可能需要抽象类,并且不能实例化一个单独的祖先,仅仅因为未知如何实现一些方法。

标记一个类为抽象告诉编译器有:

  • 例1
    如果你需要一个CarBicycle一个祖先,你可能会创建一个Vehicle类。你不能启动这个Vehicle类,因为它是未完成的。 A Vehicle本身不起作用。这就是为什么Vehicle将是抽象的。

  • 实施例2
    从.NET框架另一个实例。 Stream类是提供基本I/O功能的抽象类。它提供了一个读写方法来处理下层流的字节。

该物流可以是FileStreamNetworkStreamMemoryStream,等等。 Stream本身不知道如何读取或写入流的具体实现。但是实现了Stream的一些方法,因为它们被流的所有实例共享。

这是不可能与一个接口。所以你需要创建一个类。由于ReadWrite方法无法执行,因此Stream被标记为抽象。这将阻止Stream类按原样创建。

2

抽象类绝不是必须的。你总是可以使用一个非抽象类,并为本来是抽象的方法提供存根。您也可以通过仅为受保护的构造函数提供类来近似抽象的方面。

但这不是重点。当一个类用于对一组子类的广义属性和行为进行建模时,您需要将其标记为抽象,以使您的意图清晰。

2

我知道我需要在执行应用程序的时间之间保存信息。

我大概知道我需要什么方法来完成这个。我也可以提供几种执行整个数据存储操作的各个部分的方法。

我知道我的客户根据偏好(MS Sql,Oracle)和法律(健康行业安全要求)对数据存储有不同的要求。

我该如何提供一个可以完成80%重物提升的对象,但最后的20%会自动定制?

抽象基类允许我们为每个客户自定义最后的20%,并重用基类中80%的通用代码。此外,抽象类不会受到versioning issues that interfaces face的影响,这是一项奖励。

我可以编写我的应用程序,提供抽象基类的默认实现,测试它并部署它,而不必为每个客户端拥有不同的版本。当客户请求不同的存储方法时,可以通过dependency injection在运行时提供和使用不同的实现。

6

这不是抽象类总是必要,但他们往往很方便。假设我想为特定类型的文本文件编写解析器。

// hasty code, might be written poorly 
public abstract class FileParser<T> { 
    private readonly List<T> _contents; 
    public IEnumerable<T> Contents { 
     get { return _contents.AsReadOnly(); } 
    } 

    protected FileParser() { 
     _contents = new List<T>(); 
    } 

    public void ReadFile(string path) { 
     if (!File.Exists(path)) 
      return; 

     using (var reader = new StreamReader(path)) { 
      while (!reader.EndOfStream) { 
       T value; 
       if (TryParseLine(reader.ReadLine(), out value)) 
        _contents.Add(value); 
      } 
     } 
    } 

    protected abstract bool TryParseLine(string text, out T value); 
} 

东西扔在一起,就像上面后,我已经完成了样板代码的任何FileParser -esque类需要。所有我需要为任何派生类做的只是重写一个抽象方法 - 而不是写所有处理流等乏味的东西,而且,我可以稍后轻松地添加功能 - 例如异常处理 - 它将适用于所有派生类。

相关问题