设计具有接口和抽象的类

时间:2012-12-13 17:10:54

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

嗨,大家好我是c#的新手,  我从Microsoft找到了以下答案,建议使用接口和摘要。

如果您预计要创建组件的多个版本,请创建一个抽象类。抽象类提供了一种简单易用的组件版本。通过更新基类,所有继承类都会随更改自动更新。另一方面,接口一旦创建就无法更改。如果需要新版本的接口,则必须创建一个全新的接口。

你的意思是创建组件的多个版本。请你详细说明提供的例子。

3 个答案:

答案 0 :(得分:4)

具有共享某种行为和/或属性的类似类是您何时使用基类。其中一个典型的例子是形状。你可以这样:

基础抽象类 - FourSidedShape

  • 使用GetPerimeter方法将所有四个边组合在一起。
  • 有一个GetArea方法,它是抽象的(必须由派生类定义)

派生类 - 矩形

  • 自动获取免费的GetPerimeter方法
  • 必须使用length x width
  • 实现GetArea方法

派生类 - 平行四边形

  • 自动获取免费的GetPerimeter方法
  • 必须使用base x height
  • 实现GetArea方法

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

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

答案 1 :(得分:3)

这些应该是两个问题,但我会回答它们。

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

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

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

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

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

如果您查看.Net Framework,您会发现大多数接口(IEquatableIDisposableIComparable)通常用于强制执行行为对象,而不是整个结构。

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

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。如果需要,您的继承类汽车也可以重载ToString(),或保持原样:

public class Car : Vehicle
{
    public override void Drive()
    {
        // your implementation here
    }

    public override string ToString()
    {
        return "I am a car!";
    }
}

答案 2 :(得分:0)

可能&#34;抽象类和接口之间的区别&#34;是.Net世界中最常被问到的问题。我将在理论上解释代码片段后面的区别。

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

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

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

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

  4. 接口TestInterface

    {

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

    }

    抽象类TestAbstractClass

    {

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

    }

    它将生成编译时错误: -

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

    因此我们需要省略Field Declaration以便正确编译代码。

    接口TestInterface

    {

    void getMethod();
    string getName();
    

    }

    抽象类TestAbstractClass

    {

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

    }

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

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

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

    接口TestInterface {

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

    }

    抽象类TestAbstractClass

    {

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

    }

    以上代码将生成编译时错误: -

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

    因此我们需要从接口省略构造函数声明以编译我们的代码。

    以下代码完美编译: -

    接口TestInterface {

    void getMethod(); 
    string getName(); 
    

    }

    抽象类TestAbstractClass {

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

    }

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

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

    以下代码将更好地解释: -

    将提供访问说明符设为公共(仅允许公开)

    是完全合法的

    public interface TestInterface

    {

    void getMethod(); 
    string getName(); 
    

    }

    以上代码完美编译。

    不允许向接口成员提供任何访问说明符。

    接口TestInterface

    {

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

    }

    以上代码将生成编译时错误: -

    错误1修饰符&#39; public&#39;对此项目无效。

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

    界面测试

    {

    void getMethod(); 
    string getName(); 
    

    }