OOP:理解抽象

时间:2014-05-30 06:07:10

标签: c# class oop inheritance

我已经阅读了很多文章和一些Stack Overflow问题,以便更好地理解abstraction,但我有点困惑。这就是我一直在阅读的内容:here

  

抽象是“代表没有的基本特征   代表背景细节。“抽象让你专注于   对象的作用而不是它是如何做的。

代码:

abstract class MobilePhone
}
    public void Calling();
    public void SendSMS();
}

public class Nokia1400 : MobilePhone
{

}

public class Nokia2700 : MobilePhone
{
    public void FMRadio();
    public void MP3();
    public void Camera();
}

我的问题是,当我们继承abstract class时,我们不会在子类中实现细节吗? calling()和sendSms()在超类型中没有任何实现,所以当我们在子类中实现它时,我们也应该知道背景细节。那么抽象实际上是如何在这个例子中起作用的呢?

编辑:如果您在这里寻求帮助,这些家伙会给出最佳答案:复杂性谢尔盖别列佐夫斯基

7 个答案:

答案 0 :(得分:4)

首先,您的代码中存在一些问题。

  • 抽象类确实包含没有正文的方法,并且不是抽象的,所以这不是有效的。您应该将方法设计为抽象,或者在其中提供正文。如果您希望拥有正文但希望能够覆盖该方法,则必须应用虚拟关键字。 因此,这是您对抽象类的选择:

没有身体的方法:

abstract class MobilePhone
{
    public abstract void Calling();
    public abstract void SendSMS();
}

具有可以覆盖的主体的方法:

abstract class MobilePhone
{
    public virtual void Calling()
    {
        // Code goes here.
    }

    public virtual void SendSMS()
    {
        // Code goes here.
    }
}

具有无法覆盖的正文的方法:

abstract class MobilePhone
{
    public void Calling()
    {
        // Code goes here.
    }

    public void SendSMS()
    {
        // Code goes here.
    }
}

然后还有一些问题。您的抽象类没有提供默认情况下使对象成为私有的构造函数,因此您的类Nokia1400和Nokia2700无法从基类继承,因为基类的可访问性低于抽象类。

现在,根据您创建抽象类的方式,实现它的类必须满足一些要求:

  • 当您的基类确实包含抽象成员时,它应该在您的继承类中实现。
  • 当您的基类确实包含虚拟成员时,它不应该在您的继承类中实现,但如果需要可以覆盖它。

而且,你的最后一个课程没有编译,因为它确实包含没有正文的方法。这些方法只有在抽象时才允许,然后必须在抽象类中。

以下是基于您的代码的示例:

public abstract class MobilePhone
{
    public virtual void Calling()
    {
        Console.Write("Calling");
    }

    public abstract void SendSMS();
}

public class Nokia1400 : MobilePhone
{
    public override void SendSMS()
    {
        Console.WriteLine("Sending SMS from Nokia 1400.");
    }
}

public class Nokia2700 : MobilePhone
{
    public void FMRadio()
    {
        Console.WriteLine("FM Radio");
    }

    public void MP3()
    {
        Console.Write("MP3");
    }

    public void Camera()
    {
        Console.WriteLine("Camera");
    }

    public override void SendSMS()
    {
        Console.WriteLine("Sending SMS from Nokia 2700.");
    }
}

所以,这是一个很长的帖子,但我希望它有所帮助。

答案 1 :(得分:2)

您可以使用抽象方法和虚拟方法

抽象方法必须由扩展类实现,并且没有正文。

Virtual方法确实有一个正文,但不需要重写。如果他们不是,那么基类的主体'执行虚拟方法。

有一些警告,但这是主要的想法

public abstract class MyBase
{
    public abstract void MethodMustBeImplemented();
    public virtual void DoesNotHaveToBeOverwritten()
    {
      //Do WORk
    }
}


public class Implementor: MyBase
{

}

这会抛出编译时错误,因为MethodMustBeImplemented()尚未被覆盖。

但以下情况很好

public class Implementor: MyBase
{
    public override void MethodMustBeImplemented()
    {
      //Do WORk
    }
}

答案 2 :(得分:2)

让我们在您的报价中添加缺失的详细信息:

  

抽象代表了[客户端代码需要的]基本功能   没有代表[客户端代码]的背景细节。 [什么时候   你使用]抽象[它]让你专注于对象的作用   而不是它如何做[因为你不知道哪个类   实现它]。

我相信现在很清楚。您应该从客户的角度来看待抽象,即从将使用您的MobilePhone的代码。抽象不是必要的抽象类(一个小小的领先术语) - 它也可以是一个界面。

真实示例 - 当您作为电视机的客户端时,您使用电视机的抽象(应该有不同的频道,音量控制等),但是你不关心这些抽象的确切实现是给你的(如果实现了你所需要的所有电视抽象功能)。客户应该满意,并且应该远离细节。我打赌你只是看电视,而不是特别的东芝NX-42C?

答案 3 :(得分:2)

您的困惑来自于您必须区分:

抽象类&抽象方法

抽象类永远不能被实例化,它必须由另一个类继承,然后实例化继承类。

现在回到抽象类:它可以有两种类型的方法: - 正常方法(如示例中的调用和发送方式)。 BEC。这些常规方法,它们被认为是用空体实现的,所以继承类不需要实现它们[这就是让你感到困惑]

-abstract方法:这些方法的前缀是关键词" abstract"一旦关键词abstract出现,那么继承类应该实现它们

更多地阐明: 如果方法调用()和sendingSms()我们以" abstract"为前缀。然后它应该实现

-

现在虚拟方法和覆盖是另一个概念,如果您仍然感兴趣,我可以谈谈它

答案 4 :(得分:1)

从我记得,实现一个抽象类,你填写正文。

这就像合同一样。

当你使用那个抽象类来实现它时,你同意拥有那些方法签名(那个方法名,那些返回类型的参数)和那些变量。

好处是,如果一个类实现它,你知道它(实现它的类)可以以这种方式进行通信(它具有那些方法名称,那些变量)。所以抽象类就像API的基础。

答案 5 :(得分:1)

abstract class C{
public abstract void met1();
public void met2(){
    System.out.println("Hello");
}
}

在抽象中,如果要扩展抽象类,则必须实现抽象类的无体方法,而在抽象类中实现它们的方法可能会或者可能不会在子类中获得Overridden

所以在上面的课程中,如果你扩展Class C必须在你的班级中实施met1,而met2是可选的,你甚至可以覆盖它想要。

@Override
public void met2(){
    super.met2();
}

因此,抽象实际上是隐藏了专注于SUPERCLASS的观众对SUBCLASS的实际影响。

例如:

考虑类Dog是抽象的,它有像bark()这样的方法,但扩展Dog的类将拥有自己的实现,例如你有类似BullDog的类,它扩展了Dog。

答案 6 :(得分:1)

由于基类被声明为抽象,因此无法实例化,因此您无法从基类调用这些抽象方法,只能从实现上述抽象类的派生类调用。

当您将类声明为abstract时,您说此类无法实例化。然后你可以在类中声明抽象方法,因为你不需要实现它们,因为无论如何都不能调用它们。现在,虽然从您的基类派生的任何非抽象类必须实现这些方法以允许实例化。