什么是抽象类?

时间:2009-12-16 05:20:03

标签: c# java oop

当我了解抽象类时,就说WT(H *)!!!

问题:

  1. 创建无法实例化的类有什么意义?
  2. 为什么有人想要这样的课?
  3. 抽象类变为NECESSARY的情况是什么?
  4. **如果你知道我的意思*

13 个答案:

答案 0 :(得分:16)

  1. 最常用作基类或接口(某些语言有单独的interface构造,有些则没有) - 它不知道实现(即由子类/实现类提供)
  2. 抽象和重复使用
  3. 当基类不能为方法提供有意义的默认实现时(但允许子类重用实现的非抽象部分;任何字段,非抽象方法等)
  4. 例如:

    public abstract class Stream { /* lots of code, some abstract methods */ }
    

    什么是本身?什么的流?一个文件流?一个网络?内存缓冲区?每个人可能有不同的和不相关的阅读/写作方式,但提供了一个通用的API。创建只是一个Stream会使毫无意义,但是通过abstract类,你可以代码Stream API,但不知道详细信息:

    Stream s = CreateStream(...); // I don't *care* what kind of stream
    s.Write(new byte[] {1,2,3,4,5});
    s.Close();
    

答案 1 :(得分:7)

Abstract(Base)类为您提供半具体的类来实现您的类层次结构。它们允许您做几件事:

  1. 整合常见行为(与仅定义合同的界面不同)
  2. 为函数
  3. 提供默认(以及可选择覆盖)实现
  4. 为继承层次结构提供定义明确的分支点
  5. 控制IoC注入点
  6. 列表继续。

答案 2 :(得分:5)

1)创建一个无法实例化的类有什么意义?

仅仅因为没有直接实例化的东西并不意味着它是有用的。抽象类在继承中起着重要作用,并且在其继承类的类设计中非常有用。

例如,我之前使用过抽象类来定义类必须符合的基本结构。然后我根据该抽象类定义了继承的类,如果我错过了一个必需的方法或其他东西,它可以被编译器选中。

这也允许你做的是将继承的类关联在一起,这意味着你可以假设抽象类中定义的某些方法将存在于继承的类中 - 这可能很有用。

2)为什么有人想要这样的课程

通常我使用它来确保一系列继承的类具有某些方法等。对我来说,它对于设计一组继承类的结构非常有用。

3)抽象类变得必要的情况是什么?

我认为抽象类并不是必需的,但在某些情况下使用时,它可能有用并有助于简化您正在解决的问题。

答案 3 :(得分:2)

重点是指定派生类必须实现的方法,与接口相同,但也提供一些实现(接口无法做到)。严格来说,抽象类绝不是“必要的” - 但它们很有用。只需在.NET或Java标准库中搜索它们,并亲自查看它们的使用方法。你会发现有很多例子。

答案 4 :(得分:2)

抽象类仅在使用继承时才有用。您创建的子类必须实现与抽象类相同的接口,并且将继承您在抽象类中定义的一些基本实现。

答案 5 :(得分:2)

抽象类是无法实例化的类。例如,Square,Circle或Rectangle是一种形状,可以从Shape类派生。

Shape将包含Square,Circle或Rectangle常用的代码,例如计算形状的区域。但实例化一个Shape将毫无用处,因为它是一个抽象概念,正方形,圆形和矩形是真实实体。

答案 6 :(得分:2)

它只是隐藏来自使用它的客户端的实际实现。

  • 它提供特定功能的概念实现,但不能直接实例化
  • 只能从正在实施它的类中访问。
  • 因此,使用派生类的客户端将永远不会知道该功能的实现,因为它已被抽象化。

现在你会问为什么我们需要这个,因为接口提供相同的机制..通过简单的记录器示例

interface ILogger
{
    string PrepareLog(System.Exception ex);
    void InitializeLogger(string Type);
    int WriteLog(string msg);
}

任何日志记录客户端实现此接口都应实现所有此功能

 class EventLogger : ILogger
{
    public override void InitializeLogger(string Type)
    {
        //Event Logger Initialize   
    }
    public override int WriteLog(string msg)
    {
        //Write to event log
        return 1;
    }
    public override string PrepareLog(System.Exception ex)
    {
      return ex.StackTrace ;
    }
}

class FileLogger : ILogger
{
    public override void InitializeLogger(string Type)
    {

    }
    public override int WriteLog(string msg)
    {
        //Write to File
        return 1;
    }
    public override string PrepareLog(System.Exception ex)
    {
      return ex.StackTrace ;
    }
}


class MailLogger : ILogger
{
    public override void InitializeLogger(string Type)
    {

    }
    public override int WriteLog(string msg)
    {
        //Write to mail
        return 1;
    }

    public override string PrepareLog(System.Exception ex)
    {
        //prepare HTML Formatted msg
        return ex.StackTrace ;
    }
}

类EventLogger,FileLogger和maillogger实现了iLogger并提供了特定于上下文的实现。现在我们想要隐藏PrepareLog的实际实现,这将执行从异常对象准备日志消息的常见操作。

在我们目前的实施中,我们没有选择使单一方法具体化,而其他方法只是合同。

所以我们可以用抽象类

来改变实现
abstract class AbstractLogger:ILogger
{
    #region ILogger Members

    public virtual string PrepareLog(System.Exception ex)
    {
        return ex.StackTrace;
    }

    public abstract void InitializeLogger(string Type);
    public abstract int WriteLog(string msg);

    #endregion
}


class EventLogger : AbstractLogger
{
    public override void InitializeLogger(string Type)
    {
        //Event Logger Initialize   
    }
    public override int WriteLog(string msg)
    {
        //Write to event log
        return 1;
    }
}

class FileLogger : AbstractLogger
{
    public override void InitializeLogger(string Type)
    {

    }
    public override int WriteLog(string msg)
    {
        //Write to File
        return 1;
    }
}

class DBLogger : AbstractLogger
{
    public override void InitializeLogger(string Type)
    {

    }
    public override int WriteLog(string msg)
    {
        //Write to DB
        return 1;
    }
}

class MailLogger : AbstractLogger
{
    public override void InitializeLogger(string Type)
    {

    }
    public override int WriteLog(string msg)
    {
        //Write to mail
        return 1;
    }

    public override string PrepareLog(System.Exception ex)
    {
        //prepare HTML Formatted msg
        return ex.StackTrace ;
    }
}

现在我已经创建了 AbstractLogger 类,该类继承自iLogger并单独实现了PrepareLog方法,其余为抽象方法。所以消费者会在实现中编写特定于上下文的代码。

所以现在PrepareLog方法完全隐藏(意思是日志准备)来自cosumers初始化任何Logger。

那么为什么PrepareLog是Virtual ed ??

在某些情况下,消费者可能希望覆盖preparelog方法,Ex:MailLogger将覆盖PrepareLog并格式化HTML格式的输出以提供给邮件消息。

答案 7 :(得分:1)

抽象类是抽象。它保证行为存在,但不强制行为的实施方式。如果您以后决定要这样做,这可以让您自由地改变行为的实现方式。

抽象就像键盘,显示器或手机。所有键盘都能输入数据;所有显示器都能够显示像素;并且所有手机都有能力拨打电话。但是这些项目的制造商有不同的方式来实现这种行为。

因此,当您想要拨打电话时,您几乎可以通过任何手机进行呼叫,因为所有手机制造商都会制造出符合手机常见抽象概念的手机。如果您已经学会了如何在BlackBerry或LG上进行呼叫,则无需重新学习如何在三星上拨打电话。

手机是手机,抽象类的子类都是抽象类

答案 8 :(得分:1)

抽象类的目的是定义(限制)您的接口,而不描述实现。

  1. 可以通过构造具有派生类类型的兼容对象来实例化抽象类。

  2. 实现一个隐藏丑陋平台特定代码的干净界面。也是为了隐藏任何暴露的私人。 (这样你就真的被迫使用带有抽象接口的类。)

  3. 当您有两个完全不同的同一类的不同实现时,这是必要的。想想文件,套接字和内存块。所有这些都可以使可读数据可用 - 使用抽象类,您可以通过三种不同的方式实现这三种,即使使用代码(调用站点)是以支持所有三种方式编写的。

    < / LI>

答案 9 :(得分:1)

接口和抽象类都会促进代码库中的松散耦合。抽象类是接口和具体类之间的折衷,因为抽象类可以具有实现行为的实际方法。

通常,更喜欢接口。如果您的继承树具有子类使用的常用操作,则抽象类很有用。但即使在这里,您也可能希望声明您的抽象类实现了一个接口。 Josh Bloch将此称为“抽象接口”模式。这允许您部署甚至抽象类的不同实现,这实际上并不完全是抽象的 - 只有接口才是。

答案 10 :(得分:0)

好的,现在您创建了一个界面,其中包含每个实现中更改的所有方法。 在编程时,您会注意到某些代码块由接口的所有实现共享。

这些代码块应该放在抽象类中,而不是在每个实现中重复。这样,当某些内容发生变化时,您只需在抽象类中而不是在每个实现中修复代码。

它只是抽象的,因为你希望所有的继承类都有自己的实现。

答案 11 :(得分:0)

抽象类通过能够创建一个体现概念而不是具体事物的类来实现有用的目的。例如,动物可以是一个类,但没有人只是一个动物,它可以是 Bird Dog Cat < / strong>等是不同种类的动物。希望这可以帮助。它还与继承和多态等概念结合使用。

答案 12 :(得分:0)

与接口相同,抽象类是合同,您在其中提供了适用于许多方案的一些通用(或抽象)功能,但期望实现者为每个场景提供特定和/或不同的某些功能。有人提到Stream示例 - 非常好的例子。