mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 21:01:10 +00:00
Updata commit hash
This commit is contained in:
parent
b0ea54cbb0
commit
3204ea06bb
1 changed files with 31 additions and 31 deletions
|
@ -1,13 +1,13 @@
|
|||
# Class
|
||||
|
||||
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/type/04_class.md&commit_hash=51de3c9d5a9074241f55c043b9951b384836b258)
|
||||
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/type/04_class.md&commit_hash=1ae76335017dda8c599203146232956aa8b5b73e)
|
||||
|
||||
Erg 中的類大致是一種可以創建自己的元素(實例)的類型。
|
||||
這是一個簡單類的示例。
|
||||
|
||||
```python
|
||||
Person = Class {.name = Str; .age = Nat}
|
||||
# 如果 `.new` 沒有定義,那么 Erg 將創建 `Person.new = Person::__new__`
|
||||
# 如果 `.new` 沒有定義,那麼 Erg 將創建 `Person.new = Person::__new__`
|
||||
Person.
|
||||
new name, age = Self::__new__ {.name = name; .age = age}
|
||||
|
||||
|
@ -25,10 +25,10 @@ print! classof(john) # Person
|
|||
請注意,以下不帶換行符的定義將導致語法錯誤。
|
||||
|
||||
```python
|
||||
Person.new name, age = ... # 語法錯誤:不能直接在對象上定義屬性
|
||||
Person.new name, age = ... # 語法錯誤:不能直接在對像上定義屬性
|
||||
```
|
||||
|
||||
> __Warning__:這是最近添加的規范,后續文檔中可能不會遵循。 如果你發現它,請報告它。
|
||||
> __Warning__:這是最近添加的規範,後續文檔中可能不會遵循。如果你發現它,請報告它。
|
||||
|
||||
## 實例和類屬性
|
||||
|
||||
|
@ -57,11 +57,11 @@ Person = Class {
|
|||
}
|
||||
```
|
||||
|
||||
元素屬性(在記錄中定義的屬性)和類型屬性(也稱為實例/類屬性,尤其是在類的情況下)是完全不同的東西。 類型屬性是類型本身的屬性。 當一個類型的元素本身沒有所需的屬性時,它指的是一個類型屬性。 元素屬性是元素直接擁有的唯一屬性。
|
||||
為什么要進行這種區分? 如果所有屬性都是元素屬性,那么在創建對象時復制和初始化所有屬性將是低效的。
|
||||
元素屬性(在記錄中定義的屬性)和類型屬性(也稱為實例/類屬性,尤其是在類的情況下)是完全不同的東西。類型屬性是類型本身的屬性。當一個類型的元素本身沒有所需的屬性時,它指的是一個類型屬性。元素屬性是元素直接擁有的唯一屬性。
|
||||
為什麼要進行這種區分?如果所有屬性都是元素屬性,那麼在創建對象時復制和初始化所有屬性將是低效的。
|
||||
此外,以這種方式劃分屬性明確了諸如“該屬性是共享的”和“該屬性是分開持有的”之類的角色。
|
||||
|
||||
下面的例子說明了這一點。 `species` 屬性對所有實例都是通用的,因此將其用作類屬性更自然。 但是,屬性 `name` 應該是實例屬性,因為每個實例都應該單獨擁有它。
|
||||
下面的例子說明了這一點。 `species` 屬性對所有實例都是通用的,因此將其用作類屬性更自然。但是,屬性 `name` 應該是實例屬性,因為每個實例都應該單獨擁有它。
|
||||
|
||||
```python
|
||||
Person = Class {name = Str}
|
||||
|
@ -85,7 +85,7 @@ alice.describe() # 類型: human
|
|||
alice.greet() # 你好,我是愛麗絲
|
||||
```
|
||||
|
||||
順便說一下,如果實例屬性和類型屬性具有相同的名稱和相同的類型,則會發生編譯錯誤。 這是為了避免混淆。
|
||||
順便說一下,如果實例屬性和類型屬性具有相同的名稱和相同的類型,則會發生編譯錯誤。這是為了避免混淆。
|
||||
|
||||
```python
|
||||
C = Class {.i = Int}
|
||||
|
@ -95,14 +95,14 @@ C.i = 1 # 屬性錯誤:`.i` 已在實例字段中定義
|
|||
## 類(Class), 類型(Type)
|
||||
|
||||
請注意,`1` 的類和類型是不同的。
|
||||
只有一個類 `Int` 是 `1` 的生成器。 可以通過`classof(obj)`或`obj.__class__`獲取對象所屬的類。
|
||||
相比之下,`1`有無數種。 例如,`{1}, {0, 1}, 0..12, Nat, Int, Num`。
|
||||
但是,可以將最小類型定義為單一類型,在本例中為“{1}”。 可以通過`Typeof(obj)`獲取對象所屬的類型。 這是一個編譯時函數。
|
||||
只有一個類 `Int` 是 `1` 的生成器。可以通過`classof(obj)`或`obj.__class__`獲取對象所屬的類。
|
||||
相比之下,`1`有無數種。例如,`{1}, {0, 1}, 0..12, Nat, Int, Num`。
|
||||
但是,可以將最小類型定義為單一類型,在本例中為“{1}”。可以通過`Typeof(obj)`獲取對象所屬的類型。這是一個編譯時函數。
|
||||
對象可以使用補丁方法以及類方法。
|
||||
Erg 不允許您添加類方法,但您可以使用 [patch](./07_patch.md) 來擴展類。
|
||||
|
||||
您還可以從現有類([Inheritable](./../27_decorator.md/#inheritable) 類)繼承。
|
||||
您可以使用 `Inherit` 創建一個繼承類。 左側的類型稱為派生類,右側的“繼承”的參數類型稱為基類(繼承類)。
|
||||
您可以使用 `Inherit` 創建一個繼承類。左側的類型稱為派生類,右側的“繼承”的參數類型稱為基類(繼承類)。
|
||||
|
||||
```python
|
||||
MyStr = Inherit Str
|
||||
|
@ -111,7 +111,7 @@ MyStr.
|
|||
`-` self, other: Str = self.replace other, ""
|
||||
|
||||
abc = MyStr.new("abc")
|
||||
# 這里的比較是向上的
|
||||
# 這裡的比較是向上的
|
||||
assert abc - "b" == "ac"
|
||||
```
|
||||
|
||||
|
@ -128,10 +128,10 @@ InheritableMyStr = Inherit Str
|
|||
MyStr3 = Inherit InheritableMyStr # OK
|
||||
```
|
||||
|
||||
`Inherit Object` 和 `Class()` 在實踐中幾乎是等價的。 一般使用后者。
|
||||
`Inherit Object` 和 `Class()` 在實踐中幾乎是等價的。一般使用後者。
|
||||
|
||||
類具有與類型不同的等價檢查機制。
|
||||
類型基于其結構進行等效性測試。
|
||||
類型基於其結構進行等效性測試。
|
||||
|
||||
```python
|
||||
Person = {.name = Str; .age = Nat}
|
||||
|
@ -151,7 +151,7 @@ Person == Human # 類型錯誤:無法比較類
|
|||
|
||||
## 與結構類型的區別
|
||||
|
||||
我們說過類是一種可以生成自己的元素的類型,但這并不是嚴格的描述。 事實上,一個記錄類型+補丁可以做同樣的事情。
|
||||
我們說過類是一種可以生成自己的元素的類型,但這並不是嚴格的描述。事實上,一個記錄類型+補丁可以做同樣的事情。
|
||||
|
||||
```python
|
||||
Person = {.name = Str; .age = Nat}
|
||||
|
@ -165,11 +165,11 @@ john = Person.new("John Smith", 25)
|
|||
使用類有四個優點。
|
||||
第一個是構造函數經過有效性檢查,第二個是它的性能更高,第三個是您可以使用符號子類型(NST),第四個是您可以繼承和覆蓋。
|
||||
|
||||
我們之前看到記錄類型 + 補丁也可以定義一個構造函數(某種意義上),但這當然不是一個合法的構造函數。 這當然不是一個合法的構造函數,因為它可以返回一個完全不相關的對象,即使它調用自己`.new`。 在類的情況下,`.new` 被靜態檢查以查看它是否生成滿足要求的對象。
|
||||
我們之前看到記錄類型 + 補丁也可以定義一個構造函數(某種意義上),但這當然不是一個合法的構造函數。這當然不是一個合法的構造函數,因為它可以返回一個完全不相關的對象,即使它調用自己`.new`。在類的情況下,`.new` 被靜態檢查以查看它是否生成滿足要求的對象。
|
||||
|
||||
~
|
||||
|
||||
類的類型檢查只是檢查對象的`。 __class__` 對象的屬性。 因此可以快速檢查一個對象是否屬于一個類型。
|
||||
類的類型檢查只是檢查對象的`。 __class__` 對象的屬性。因此可以快速檢查一個對像是否屬於一個類型。
|
||||
|
||||
~
|
||||
|
||||
|
@ -192,7 +192,7 @@ john.bark() # "Yelp!"
|
|||
```
|
||||
|
||||
`Dog` 和 `Person` 的結構完全一樣,但讓動物打招呼,讓人類吠叫顯然是無稽之談。
|
||||
前者是不可能的,所以讓它不適用更安全。 在這種情況下,最好使用類。
|
||||
前者是不可能的,所以讓它不適用更安全。在這種情況下,最好使用類。
|
||||
|
||||
```python
|
||||
Dog = Class {.name = Str; .age = Nat}
|
||||
|
@ -202,12 +202,12 @@ Person = Class {.name = Str; .age = Nat}
|
|||
Person.greet self = log "Hello, my name is {self.name}."
|
||||
|
||||
john = Person.new {.name = "John Smith"; .age = 20}
|
||||
john.bark() # 類型錯誤: `Person` 對象沒有方法 `.bark`。
|
||||
john.bark() # 類型錯誤: `Person` 對像沒有方法 `.bark`。
|
||||
```
|
||||
|
||||
另一個特點是補丁添加的類型屬性是虛擬的,實現類不作為實體保存。
|
||||
也就是說,`T.x`、`T.bar` 是可以通過與 `{i = Int}` 兼容的類型訪問(編譯時綁定)的對象,并且未在 `{i = Int}` 或 ` C`。
|
||||
相反,類屬性由類本身持有。 因此,它們不能被不處于繼承關系的類訪問,即使它們具有相同的結構。
|
||||
也就是說,`T.x`、`T.bar` 是可以通過與 `{i = Int}` 兼容的類型訪問(編譯時綁定)的對象,並且未在 `{i = Int}` 或 ` C`。
|
||||
相反,類屬性由類本身持有。因此,它們不能被不處於繼承關係的類訪問,即使它們具有相同的結構。
|
||||
|
||||
```python
|
||||
C = Class {i = Int}
|
||||
|
@ -232,8 +232,8 @@ C.new({i = 1}).bar # <方法 bar>
|
|||
## 與數據類的區別
|
||||
|
||||
有兩種類型的類:常規類,通過`Class`成為記錄類,以及從記錄類繼承(`Inherit`)的數據類。
|
||||
數據類繼承了記錄類的功能,具有分解賦值、默認實現的`==`和`hash`等特性。另一方面,數據類有自己的等價關系和格式展示。
|
||||
另一方面,如果要定義自己的等價關系或格式顯示,則應使用普通類。
|
||||
數據類繼承了記錄類的功能,具有分解賦值、默認實現的`==`和`hash`等特性。另一方面,數據類有自己的等價關係和格式展示。
|
||||
另一方面,如果要定義自己的等價關係或格式顯示,則應使用普通類。
|
||||
|
||||
```python
|
||||
C = Class {i = Int}
|
||||
|
@ -243,15 +243,15 @@ print! c # <C object>
|
|||
c == d # 類型錯誤:`==` 沒有為 `C` 實現
|
||||
|
||||
D = Inherit {i = Int}
|
||||
e = D.new {i = 1}
|
||||
f = D.new {i = 2}
|
||||
print! e # D{i = 1}
|
||||
e = D::{i = 1} # 與`e = D.new {i = 1}`相同
|
||||
f = D::{i = 2}
|
||||
print! e # D(i=1)
|
||||
assert e ! = f
|
||||
```
|
||||
|
||||
## 枚舉類
|
||||
|
||||
為了便于定義“Or”類型的類,提供了一個“Enum”。
|
||||
為了便於定義“Or”類型的類,提供了一個“Enum”。
|
||||
|
||||
```python
|
||||
X = Class()
|
||||
|
@ -260,7 +260,7 @@ XorY = Enum X, Y
|
|||
```
|
||||
|
||||
每種類型都可以通過`XorY.X`、`XorY.Y`來訪問,構造函數可以通過`XorY.cons(X)`獲得。
|
||||
`.cons` 是一個接受類并返回其構造函數的方法。
|
||||
`.cons` 是一個接受類並返回其構造函數的方法。
|
||||
|
||||
```python
|
||||
x1 = XorY.new X.new()
|
||||
|
@ -268,9 +268,9 @@ x2 = XorY.cons(X)()
|
|||
assert x1 == x2
|
||||
```
|
||||
|
||||
## 類關系
|
||||
## 類關係
|
||||
|
||||
類是需求類型的子類型。 類中可以使用需求類型的方法(包括補丁方法)。
|
||||
類是需求類型的子類型。類中可以使用需求類型的方法(包括補丁方法)。
|
||||
|
||||
```python
|
||||
T = Trait {.foo = Foo}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue