【问题标题】:Designing of classes with interface and abstract设计带有接口和抽象的类
【发布时间】:2012-12-13 17:10:53
【问题描述】:

大家好,我是 C# 新手, 我从微软那里找到了以下答案,使用接口和抽象的建议。

如果您希望创建组件的多个版本,请创建一个抽象类。抽象类提供了一种简单易行的方式来对组件进行版本控制。通过更新基类,所有继承类都会随着更改而自动更新。另一方面,接口一旦创建就不能更改。如果需要新版本的接口,则必须创建一个全新的接口。

创建组件的多个版本是什么意思。你能详细说明更多提供的例子吗?

【问题讨论】:

  • 问题 2 应该是一个单独的问题。这里有一个快速链接可以帮助你msdn.microsoft.com/en-us/library/2cf62fcy.aspx
  • 我已经删除了问题 2,因为在 Stack Overflow 上一次只需要问一个问题(有充分的理由)。请单独询问(更好的是,谷歌它 - 它已经被回答了!)。
  • 在 MSDN 中搜索 Create Multiple version component .net
  • 看到这个类似的问题:stackoverflow.com/questions/11700446/… 注意:我认为“无法更改”可能是 COM 保留?在 .NET 中看起来很奇怪。

标签: .net c#-4.0 c#-3.0


【解决方案1】:

拥有共享某种行为和/或属性的相似类是您使用基类的时候。典型的例子之一是形状。你可以这样:

基础抽象类 - FourSidedShape

  • 具有将所有四个边相加的 GetPerimeter 方法。
  • 有一个 GetArea 方法,它是抽象的(必须由派生类定义)

派生类 - 矩形

  • 自动免费获取GetPerimeter方法
  • 必须实现 GetArea 方法,使用长 x 宽

派生类 - 平行四边形

  • 自动免费获取GetPerimeter方法
  • 必须使用底 x 高度实现 GetArea 方法

您的派生类还可以添加任何他们想要的不属于基类的独特行为。

注意:抽象类是不能直接实例化的。您必须使用派生类之一。

【讨论】:

    【解决方案2】:

    这确实应该是两个问题,但我会同时回答它们。

    第二个第一:可空类型的用法是:

    decimal? priceFromDb = datarow.Field<decimal?>("price");
    

    在这种情况下,您声明的类型将包含十进制值,但可能为 null,因为在这种情况下,它来自数据库,并且基础字段可能为 null。声明可空类型的正确方法是在类型名称的末尾使用?。然后,当您想使用有问题的值时,您可以执行以下操作:

    if (priceFromDb.HasValue)
    {
        Console.WriteLine("The price is {0}.", priceFromDb.Value);
    }
    

    第一个问题: C# 中使用接口来确保类或结构实现您需要的某些关键功能。它们通常只包含少数方法,通常不超过一两个,其想法是一旦您创建了一个已发布的接口,它就不会改变。另一方面,抽象类使您能够强制类实现您需要的方法,并为它们提供通用功能,如果您将来对抽象类进行更改,例如,添加更多通用特征,继承类自动获取特征。使用抽象类并不是发布重大更改的许可,它只是一种将通用特性组合到一个更干净的函数中的类的方法。我能描述的最好方法是使用抽象类来定义对象及其子对象的核心属性,并使用接口来描述类的一个关键行为。

    如果您查看 .Net 框架,您会发现大多数接口(@98​​7654321@、IDisposableIComparable)通常用于在对象上强制执行行为,而不是整个结构。

    例如,考虑一个抽象类车辆:

    abstract class Vehicle
    {
        public int NumWheels { get; set; }
        public string Name { get; set; }
        public abstract void Drive();
        public override string ToString()
        {
            return "I am a vehicle!";
        }
    }
    

    您可以创建一个继承自 Vehicle 的汽车对象,并且需要实现 Drive(),但将免费获得 NumWheelsName 两个属性。如果需要,您的继承类 car 也可以重载 ToString(),或者保持原样:

    public class Car : Vehicle
    {
        public override void Drive()
        {
            // your implementation here
        }
    
        public override string ToString()
        {
            return "I am a car!";
        }
    }
    

    【讨论】:

      【解决方案3】:

      可能“抽象类和接口之间的区别”是 .Net 世界中最常见的问题。我将解释理论上的差异,然后是代码 sn-p。

      根据我的理论,抽象类和接口之间基本上有5个区别,如下所示:-

      1. 一个类可以实现任意数量的接口,但一个子类最多只能使用一个抽象类。

      2. 抽象类可以有非抽象方法(具体方法),而在接口的情况下,所有方法都必须是抽象的。

      3. 抽象类可以声明或使用任何变量,而接口不允许这样做。 所以下面的代码不会编译:-

      接口测试接口

      {

      int x = 4;  // Filed Declaration in Interface 
      
      void getMethod(); 
      
      string getName(); 
      

      }

      抽象类TestAbstractClass

      {

      int i = 4; 
      int k = 3; 
      public abstract void getClassName(); 
      

      }

      它会产生一个编译时错误:-

      错误 1 ​​接口不能包含字段。

      所以我们需要省略字段声明才能正确编译代码。

      接口测试接口

      {

      void getMethod();
      string getName();
      

      }

      抽象类TestAbstractClass

      {

      int i = 4; 
      int k = 3; 
      public abstract void getClassName(); 
      

      }

      上面的代码可以正确编译,因为接口中没有字段声明。

      4.抽象类可以有构造函数声明,而接口不能有。

      所以下面的代码不会编译:-

      接口测试接口 {

      // Constructor Declaration 
      public TestInterface() 
      { 
      void getMethod(); 
      string getName(); 
      }
      

      }

      抽象类TestAbstractClass

      {

      public TestAbstractClass() 
      { 
      int i = 4; 
      int k = 3; 
      public abstract void getClassName(); 
      }
      

      }

      上面的代码会产生一个编译时错误:-

      错误 1 ​​接口不能包含构造函数

      所以我们需要在接口中省略构造函数声明才能编译我们的代码。

      以下代码完美编译:-

      接口测试接口 {

      void getMethod(); 
      string getName(); 
      

      }

      抽象类TestAbstractClass {

      public TestAbstractClass() 
      { 
      int i = 4; 
      int k = 3; 
      public abstract void getClassName(); 
      
      }
      

      }

      5.一个抽象类允许对其所有成员声明具有所有访问修饰符,而在接口中我们不能声明任何访问修饰符(包括公共),因为接口的所有成员都是隐式公共的。

      注意:这里我说的是接口成员的访问说明符,而不是接口。

      下面的代码会更好地解释它:-

      提供访问说明符为 Public 是完全合法的(记住只允许 public)

      公共接口TestInterface

      {

      void getMethod(); 
      string getName(); 
      

      }

      以上代码编译完美。

      不允许给接口的成员任何访问说明符。

      接口测试接口

      {

      public void getMethod(); 
      public string getName(); 
      

      }

      上面的代码会产生一个编译时错误:-

      错误 1 ​​修饰符“public”对此项无效。

      但声明接口的最佳方式是避免接口上的访问说明符以及接口的成员。

      接口测试

      {

      void getMethod(); 
      string getName(); 
      

      }

      【讨论】:

        猜你喜欢
        • 2019-08-07
        • 2017-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多