2010-03-06 96 views
23

兩者都不可實例化。有什麼區別,在哪些情況下你可以使用其中一種?抽象類和靜態類之間有什麼區別?

+2

記住在使用靜態類時要考慮線程安全性。 [see here](http://stackoverflow.com/questions/1090650/are-static-methods-thread-safe) – kenchilada 2013-07-08 14:44:58

回答

19

static表示該類只能有靜態成員,並且不能創建它的一個實例。這用於無狀態功能(例如,只定義擴展方法或實用程序方法的類型)。您也可以在非靜態類上聲明成員static。這允許您將功能附加到某個類型,而無需實例化它。

Here's more detail on using static members and classes

abstract s定義了所有派生類型共享的基本結構和功能,但不能單獨使用。我想,把它們想象成藍圖和合同。這是面向對象的核心概念。

Here's more detail on using abstracts

+3

c#中的一個靜態類是一個密封的抽象類 – 2016-09-21 17:00:35

2

抽象類通過派生類間接實例化。它們提供通用行爲和實例狀態,但表示需要更多,並且必須由派生的具體類提供。例如,Transform可能是一個抽象類:它聲明瞭一個通用的Apply(Shape)方法,但沒有實現該方法。像RotationTranslation這樣的具體派生類將實現該方法,並且那些類可以被實例化。

靜態類不能實例化,並且任何狀態都在類級而不是實例級。它們通常用於定義沒有與方法關聯的狀態的效用方法。 Transform不能是一個靜態類,因爲具體派生類需要每個實例狀態(例如,Rotation需要每個實例Angle,因爲不同的Rotation變換可能是不同的角度)。

15

這裏是一個簡短的總結:

  • 靜態類只能包含static成員(它只是一個不邏輯上屬於任何標準的類的實例方法的容器)
  • 抽象類可以cotnain所有常見類型的成員(靜態,抽象的,也實例)

的主要區別是,你可以從abstract類繼承,但你不能從一個static類繼承。從技術上講,.NET運行時沒有任何static類的概念,所以C#編譯器將它們作爲abstractsealed(意味着您不能從它們繼承)的類來遵守它們。

所以,staticabstract類,也sealed(雖然這不是看待這個問題,如果你是C#程序員通常的方式),並且只包含static成員(由C#編譯器執行)。

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); 
} 

在這裏,用戶的緩存是一種常見的關注,在基本情況下爲藍本,而實際retreival留給子類來提供。

靜態類是完全不同的事情。他們基本上是保持你的實用功能的地方:

static class StrUtil { 

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

把它們當作某種特殊的命名空間,它只能包含靜態成員。基本上是放置功能的地方。

7

抽象類旨在用作類繼承層次結構的基礎。靜態類不可能是是類繼承層次結構的基礎。

靜態類用於單態或無狀態功能。抽象類不適用於單例功能,因爲即使它可能包含靜態方法和字段,但它不能禁止繼承,所以單例使用可能會被子類擊敗。或者,至少它會讓其他程序員感到困惑,因爲它的定義會傳達一個與其實際使用目的不同的意圖。

抽象類和靜態類之間的表面相似性僅在於兩者都不可實例化。除此之外,它們是完全不同的使用情況完全不同的動物。

6

CLR沒有靜態類的概念,它特定於C#。編譯器通過使用類的CLR屬性來實現它:它聲明它是抽象的密封的。這可以防止任何語言實例化這樣的類。這是個什麼樣子,你跑的時候喜歡ILDASM:

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

製作它的密封是非常靜態類的點,它被用作靜態方法和字段的容器。這使得它們像全局變量和函數一樣行事,就像你在C或Pascal等語言中一樣。

抽象類非常相反,它被設計爲派生自。抽象類具有全部其成員抽象行爲就像一個接口。 C#有一個關鍵字,使靜態類和接口成爲完全相反的對象。

+0

+1用於指出靜態類是密封的,在引擎蓋下抽象。 – Firestrand 2010-03-06 03:38:16

1

抽象類的主要目的是定義一個或多個抽象方法。 擴展Abstract類的任何類都將實現抽象方法,否則它也需要聲明爲「Abstract」。

但是,它也可以在沒有實現任何抽象方法的情況下聲明一個類爲「Abstract」。請參閱下面的示例。

公共抽象類AbstractTest {

public void abcd(){} 

public static void main(String[] args) { 

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

} 

}

只有內部類可以聲明爲 「靜態」,請參見下面的代碼。 上層/封裝類不能聲明爲「靜態」。 可以通過使用Upper/encapsulating類變量來訪問它.Static-inner-classname與使用類名稱的任何靜態方法調用相同。

公共類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"); 
    } 
} 

}兩者之間

-1

主要區別是可擴展性。

CLR馬克所有「靜態」類爲「抽象&密封」幕後(即,它們不能因此繼承不能延長)和含有節目或命名空間時,會自動.NET框架CLR加載它們加載。這會在運行時帶來性能提升。

「抽象」類背後的哲學是在一個地方大寫所有擴展類的所有共同特徵。

希望它有幫助。

相關問題