> For the complete documentation index, see [llms.txt](https://kurohasu.gitbook.io/fsharpabout/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kurohasu.gitbook.io/fsharpabout/objects/class-method.md).

# クラスとメンバー

オブジェクトには定数や関数を定義した「メンバー」が必要になります\
メンバーには「プロパティ」や「メソッド」などがあげられます

### クラスの宣言

クラスの宣言を行うには「type」キーワードを使用して宣言します\
基本構文は以下の通りです

```
構文:type クラス名(<引数>) [as 自己識別子]=
    [inherit 継承元クラス(引数)]
    [let 処理orプロパティ...]
    [do 処理...]
    member 自己識別子.メソッド(<引数>)=処理...

クラスのインスタンス作成:
    let インスタンス名=new クラス名(<引数>)    
```

クラス内にある「let」は通常と同様に値もしくは関数としてコンパイルされます\
また「do」キーワードでは、インスタンスが作成されるときに1度だけ実行する処理を記述できます

```fsharp
//1 インスタンス作成時にメッセージを表示する「dotest」クラス
type dotest()=
    do printfn "dotest class created"

//2 「msg」プロパティの表示と関数「printmsg」を実行する「lettest」クラス
type lettest()=
    let msg="lettest-str"
    let printmsg()=printfn "%s is done!" msg    
    
    //メンバーとして実装
    member _.outmsg()=printfn "msg is %s" msg    
    member _.doprintmsg()=printmsg()

//インスタンス作成
let box1=new dotest()    //この時点でdo処理が実行される
let box2=new lettest()

box2.outmsg()
box2.doprintmsg()

//出力結果:
//cl class created
//msg is lettest-str
//lettest-str is done!
```

### メソッドについて

メソッドはクラス内で関数を定義したものです。\
オブジェクト指向ではこのメソッドが主役となっていきます。\
また、staticと記述することでインスタンスを作成することなく実行できるようになり\
inlineと記述するとメンバーのインライン展開も行えます。

```
構文:
    ①member 自己識別子.メソッド名(<引数>)=
        処理...

    ②static member 静的メソッド名(<引数>)=
        処理...

    ③member inline 自己識別子.インラインメソッド名(<引数>)=
        処理...

呼び出し:
    ①インスタンス.メソッド名(<引数>)
    ②クラス名.静的メソッド名(<引数>)
    ③クラス名.インラインメソッド名(<引数>)
```

```fsharp
//例
type methodtests()=
    member _.normal()=printfn "normal method"    //通常メソッド

    static member stat()=printfn "static method"    //静的メソッド

    member inline _.inl()=printfn "inline method"    //インラインメソッド


let box=new methodtests()

//呼び出し
box.normal()
membertests.stat()
box.inl()


//出力結果:
//normal method
//static method
//inline method
```

{% hint style="info" %}
自己識別子を省略する場合thisもしくは\_(アンダーバー)のみの記述でOKです
{% endhint %}

### プロパティについて

プロパティはクラス内で値を定義したものを指します\
let宣言した値を参照させるためによく使用されています\
デフォルトでは読み込み専用となっていますが「アクセサー」を記述するとプロパティへの書き込み\
が可能となります(書き込みを行う場合は変数宣言時にmutableを忘れないでください！)

```
構文:
    ①読み込み専用
    member 自己識別子.値名 with get()=入手時の処理...

    ②書き込み専用
    member 自己識別子.値名 with set(<引数>)=設定時の処理...

    ③読み込み・書き込みを行う
    member 自己識別子.値名 
        with get()=入手時の処理...
        and set(<引数>)=設定時の処理...
```

```fsharp
type propatytest(x)=
    let mutable num=x    //プロパティnumに引数xを代入
    
    member _.readonly with get()=num
    //readonlyが呼び出されたら,numの値を返す

    member _.writeonly with set(n)=num<-n
    //writeonlyが呼び出されたら,numに引数nの値を代入

    member _.bothRW
        with get()=num
        and set(n)=num<-n
    //上２つの機能を有する


//呼び出し(引数n=10)
let box=new propatytest(10)

//①読み込み
box.readonly|>printfn "%d"

//②21を書き込んで出力
box.writeonly<-21
box.readonly|>printfn "%d"

//③255を書き込んで出力
box.bothRW<-255
box.readonly|>printfn "%d"


//出力結果:
//10
//21
//255
```

\
また、F#では省略可能な引数を持つメソッドの定義も行えます<br>

```
//構文(System.Runtime.InteropServicesが必要):
    member _.メソッド名([<Optional; DefaultParameterValue(値)>] <引数>) =処理...
```

他にもメソッドの継承や抽象メソッドなどもサポートされています\
次ページではオブジェクトの継承について紹介していきます
