【发布时间】:2011-01-24 08:22:00
【问题描述】:
两者都不是可实例化的。有什么区别?在什么情况下您可以使用其中一种?
【问题讨论】:
-
记住在使用静态类时要考虑线程安全。 See here
两者都不是可实例化的。有什么区别?在什么情况下您可以使用其中一种?
【问题讨论】:
static 表示类只能有静态成员,不能创建它的实例。这用于无状态功能(例如,仅定义扩展方法或实用方法的类型)。您还可以在非静态类上声明成员 static。这允许您将功能附加到类型而无需实例化它。
Here's more detail on using static members and classes。
abstracts 定义了所有派生类型共享的基本结构和功能,但不能单独使用。我想,把它们想象成一份蓝图和一份合同。这是 OOP 的核心概念。
【讨论】:
这里是一个简短的总结:
static 成员(它只是逻辑上不属于任何标准类实例的方法的容器)主要区别在于您可以从abstract 类继承,但不能从static 类继承。从技术上讲,.NET 运行时没有任何static 类的概念,因此C# 编译器将它们编译为abstract 和sealed 的类(意味着您不能从它们继承)。
所以,static 类是 abstract 类,它们也是 sealed(尽管如果您是 C# 程序员,这不是查看问题的常用方法)并且仅包含 static 成员(这是强制执行的)由 C# 编译器)。
【讨论】:
抽象类旨在用作类继承层次结构的基础。静态类不能成为类继承层次结构的基础。
静态类适用于单例状态或无状态功能。抽象类不适合单例功能,因为即使它可能像静态类一样包含静态方法和字段,它也不能禁止继承,因此单例的使用可能会被子类打败。或者,至少,它会让其他程序员感到困惑,因为它的定义会传达一种与其实际预期用途不同的意图。
抽象类和静态类之间表面上的相似之处仅在于两者都不能被实例化。除此之外,它们是完全不同的动物,有着完全不同的用例。
【讨论】:
CLR 没有静态类的概念,它是特定于 C# 的。编译器通过巧妙地使用类的 CLR 属性来实现它:它声明它是抽象的 和 密封的。这可以防止任何语言实例化这样的类。这是运行 Ildasm 时的样子:
.class public abstract auto ansi sealed beforefieldinit ConsoleApplication1.Test
extends [mscorlib]System.Object
{
}
将其密封在很大程度上是静态类的重点,它用作静态方法和字段的容器。这使得它们的行为类似于 C 或 Pascal 等语言中的全局变量和函数。
抽象类则完全相反,它被设计为派生自。具有所有其成员抽象的抽象类就像一个接口。 C# 有一个关键字,使静态类和接口完全相反。
【讨论】:
抽象类通过派生类间接实例化。它们提供共同的行为和实例状态,但表明需要更多并且必须由派生的具体类提供。例如,Transform 可能是一个抽象类:它声明了一个通用的Apply(Shape) 方法,但没有实现该方法。具体派生类如Rotation 或Translation 将实现该方法,并且这些类可以被实例化。
静态类不能被实例化,任何状态都处于类级别而不是实例级别。它们通常用于定义没有与方法关联的状态的实用方法。 Transform 不能是静态类,因为具体派生类需要每个实例的状态(例如,Rotation 需要一个每个实例的Angle,因为不同的Rotation 转换可能是不同的角度)。
【讨论】:
抽象类旨在用作基类;它们不能有直接实例。相反,您必须派生子类,这些子类提供了(通常是有意地)在抽象基类中遗漏的内容。
示例:假设您有一个复杂的应用程序,用户可以在其中登录。应该可以使用各种身份验证机制,比如 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) {
...
}
}
将它们视为某种特殊的命名空间,它只能包含静态成员。基本上是一个放置函数的地方。
【讨论】:
抽象类(基类): 允许其他类继承这个类(一个类获取另一个类的属性(方法和字段)),但是禁止实例化 即我们不能拥有此类的对象。 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
【讨论】:
抽象类的主要目的是定义一个或多个抽象方法。 任何扩展抽象类的类都将实现抽象方法,否则它也需要声明为“抽象”。
但是,也可以将一个类声明为“抽象”而不在其中实现任何抽象方法。请参阅下面的示例。
public abstract class AbstractTest {
public void abcd(){}
public static void main(String[] args) {
System.out.print("hi...");
}
}
只有内部类可以声明为“静态”,见下面的代码。 上层/封装类不能声明为“静态”。 它可以通过使用上层/封装类变量来访问。静态内部类名,即与使用类名的任何静态方法调用相同。
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");
}
}
}
【讨论】:
两者之间的主要区别在于可扩展性。
CLR 在幕后将所有“静态”类标记为“抽象和密封”(即,它们不能被继承,因此不能被扩展)和 .NET Framework CLR加载包含程序或命名空间时自动加载它们。这可以提高运行时的性能。
“抽象”类背后的理念是将所有扩展类的所有共同特征集中在一个地方。
希望对你有帮助。
【讨论】: