抽象类和静态类之间有什么区别?

时间:2010-03-06 00:03:20

标签: c# .net oop

两者都不可实现。有什么区别,在什么情况下你可能会使用其中一种?

9 个答案:

答案 0 :(得分:27)

static表示该类只能有静态成员,您无法创建它的实例。这用于无状态功能(例如,仅定义扩展方法或实用程序方法的类型)。您还可以在非静态类上声明成员static。这允许您将功能附加到类型而无需实例化它。

Here's more detail on using static members and classes

abstract定义了所有派生类型共享的基本结构和功能,但不能单独使用。我认为,将它们视为蓝图和合同。这是OOP的核心概念。

Here's more detail on using abstracts

答案 1 :(得分:21)

以下是简短摘要:

  • 静态类只能包含static个成员(它只是一个逻辑上不属于任何标准类实例的方法的容器)
  • 抽象类可以包含所有常见类型的成员(静态,抽象和实例)

关键区别在于您可以从abstract类继承,但不能从static类继承。从技术上讲,.NET运行时没有任何static类的概念,因此C#编译器将它们编译为abstractsealed的类(意味着你不能继承自它们)。

因此,static类是abstract类也是sealed(尽管如果你是C#程序员,这不是查看问题的常用方法)并且只包含{{成员(由C#编译器强制执行)。

答案 2 :(得分:7)

抽象类旨在用作类继承层次结构的基础。静态类不能成为类继承层次结构的基础。

静态类用于单例状态或无状态功能。抽象类不适用于单例功能,因为即使它可能包含静态方法和字段作为静态类,它也不能禁止继承,因此单例使用可能会被子类击败。或者,至少,它会让其他程序员感到困惑,因为它的定义会传达一个与其实际用途不同的意图。

抽象类和静态类之间的表面相似之处仅在于它们都不能被实例化。除此之外,它们是完全不同的动物,具有完全不同的用例。

答案 3 :(得分:6)

CLR没有静态类的概念,它特定于C#。编译器通过为类使用CLR属性来实现它:它声明它抽象密封。这可以防止任何语言实例化这样的类。这就是你运行Ildasm时的样子:

.class public abstract auto ansi sealed beforefieldinit ConsoleApplication1.Test
       extends [mscorlib]System.Object
{
}

使其密封非常重要的是静态类,它被用作静态方法和字段的容器。这使得它们像C或Pascal等语言一样充当全局变量和函数。

抽象类恰恰相反,它的设计源于。具有所有其成员抽象的抽象类就像一个接口。 C#有一个关键字,使静态类和接口完全相反。

答案 4 :(得分:2)

抽象类通过派生类间接实例化。它们提供了常见的行为和实例状态,但表明需要更多,并且必须由派生的具体类提供。例如,Transform可能是一个抽象类:它声明了一个公共Apply(Shape)方法,但没有实现该方法。像RotationTranslation这样的具体派生类将实现该方法,并且可以实例化这些类。

无法实例化静态类,并且任何状态都在类级别而不是实例级别。它们通常用于定义实用程序方法,其中没有与方法关联的状态。 Transform不能是静态类,因为具体派生类需要每个实例状态(例如Rotation需要每个实例Angle,因为不同的Rotation转换可以从不同的角度来看。)

答案 5 :(得分:2)

抽象类旨在用作基类;他们不能有直接的实例。相反,您必须派生子类,它提供抽象基类中(通常是故意的)遗漏的内容。

示例:假设您有一个复杂的应用程序,用户可以登录到该应用程序。应该使用各种身份验证机制,例如LDAP,NTLM,您可以使用它。在这样的上下文中建模“用户”或“主体”的一种方法是将所有这些机制中的共同点收集到抽象基类中,并将“间隙”(抽象方法)留在实际实现中发挥:

abstract class Authenticator {

   protected Dictionary<string,User> userCache;

   ...

   public User LoadUser(string name) {
        User user;
        if( userCache.TryGet(name, out user) ) return user;
        else {
            user = LoadFromStore(name);
            userCache.Add(name, user);
            return user;
        }
   }

   protected abstract User LoadFromStore(string name);
}

在这里,用户的缓存是一个常见的问题,在基本情况下建模,而实际的撤销是留给子类提供的。

静态类是完全不同的事情。它们本质上是一个保持实用功能的地方:

static class StrUtil {

    public static string TrimWhitespace(string str) {
        ...
    }
}

将它们视为某种特殊的命名空间,它只能包含静态成员。基本上,放置功能的地方。

答案 6 :(得分:1)

抽象类的主要目的是定义一个或多个抽象方法。 任何扩展Abstract类的类都将实现抽象方法,否则它也需要声明为“Abstract”。

但是,它也可以将一个类声明为“Abstract”而不在其中实现任何抽象方法。请参阅下面的示例。

公共抽象类AbstractTest {

public void abcd(){}

public static void main(String[] args) {

      System.out.print("hi...");

}

}

只有内部类可以声明为“静态”,请参阅下面的代码。 Upper / encapsulating类不能声明为“Static”。 它可以通过使用Upper / encapsulating类变量来访问.Static-inner-classname,与使用类名的任何静态方法调用相同。

public class StaticTest {

public static void main(String ag[]){
    System.out.println("hello...1");
    StaticTest.StaticTest2.meth2();
}

public static class StaticTest2 {
    public static void meth2(){
        System.out.print("hello...2");
    }
}

}

答案 7 :(得分:1)

抽象类(基类): 允许其他类从此类继承 一个类获取另一个的属性(方法和字段)),但 禁止实例化 即我们不能拥有此类的对象。 http://csharp.net-tutorials.com/classes/abstract-classes

静态类: 此类 无法实例化 。此 类也无法继承 。要访问此类的方法,可以直接使用classname.method。 https://social.technet.microsoft.com/wiki/contents/articles/21028.difference-between-static-class-sealed-class-and-abstract-class-in-c.aspx

答案 8 :(得分:-1)

两者之间的主要区别在于可扩展性。

CLR 将所有'静态'类标记为' abstract&amp;在场景后面密封'(即,它们不能被继承,因此无法扩展),并且.NET Framework CLR在加载包含程序或命名空间时自动加载它们。这样可以提高运行时的性能。

“抽象”类背后的哲学是将所有扩展类的所有共同特征都集中在一个地方。

希望它有所帮助。