スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門第44回(Object Expression)

今回のお題は「OOP(9)Object Expression」です。
 
今まで学んできた中でabstractキーワードがクラスでもインターフェイスでも出てきました。abstractキーワードがついているメソッド、プロパティを実装できるのは、クラスの場合は継承するとき、インターフェイスの場合は、そのインターフェイスを実装するクラスを定義するときでした。どちらにせよ、クラス定義が必要となります。その上でそのクラスのインスタンスを生成して始めて、実装されたメソッド、インターフェイスが実行可能となります。
このクラス定義とインスタンスの生成を同時に行うのがObject Expressionです。
Object Expressionを使った場合、この新しいクラスには名前がつきません。
とりあえず例を見てください。
 
[<AbstractClass>]               
type ExampClass (x :int) =
    abstract DispSomething : unit -> unit
    member this.X = x
    
さてこのクラスでDispSomethingに実装を加えたクラスを継承させて、初期値X=3でインスタンスを生成してみます。overrideキーワードは必要ありません。
let t = {new ExampClass(3) with
            member this.DispSomething ()=
                printfn "値は%dだよ" this.X}
 
{ new クラス型  コンストラクタ引数 with
    メンバ定義 }
という構文になっています。
実行してみるとF#Interactiveでは
 
val t : ExampClass
 
と表示されますが、正確にはExampClassのインスタンスではなく、ExampClassを継承して,DispSomethingを実装した、名無しクラス(匿名クラス)のインスタンスです。
(ExampClassはabstract classなのでインスタンスは作れません)
上のtを使ってみます。
 
> t.DispSomething();;
値は3だよ
val it : unit = ()
 
それではDispSomethingに別の実装を加えたクラスを継承させて、初期値X=3でインスタンスを生成してみます
 
let u = {new ExampClass(3) with
            member this.DispSomething ()=
                printfn "Val=%d" this.X}
実行例
 
> u.DispSomething();;
Val=3
val it : unit = ()
 
またインターフェイスから、そのインターフェイスを実装したクラスを作成して、インスタンスを生成することもできます。

 
type IExamp =
    abstract DispDefInInterface : unit -> unit 
 
let v = {
            new IExamp with
                member this.DispDefInInterface () =
                        printfn "インターフェイスの実装です"  }
 
 { new インターフェイス型 with
    メンバ定義}
の形の構文になっています。
 
 
実行例
val v : IExamp
 
> v.DispDefInInterface();; //キャストなしで呼び出せます。
インターフェイスの実装です
val it : unit = ()
 
 
これもIExampのインスタンスではありません。インターフェイスのみからはインスタンスは生成できません。(IExampインターフェイスを実装した名無しのクラスのインスタンスです。)F#InteractveはIExampと表示します。
 
さて、これがどのような場合に役に立つかということですが、例としてListのsortメソッドを使う場合を紹介します。
まずint*float*int list型のResizeArrayをtで束縛します。
 
let t = new ResizeArray<_> ([|(1,0.1,2);(3,5.9,5);(-3,-1.1,6);(-3,2.0,-2);(2,8.5,-5)|])//型推論を使わない場合は<_>を<int*float*int>とします。
 
これを、色々な基準でソートすることを考えます。
Sortメソッドを使うとすると、引数はcomparer: System.Collections.Generic.IComparer<int * float * int>となります。
よってIComparer<int * float * int>インターフェイスを実装したクラスのインスタンスが必要となります。
このインターフェイスの要求条件はCompare : 'a * 'a -> intというメソッドを実装していることです。(この場合の'aはint * float * int)このメソッドを使って二つの要素を比較して並べ替えます。
 
それでは、第2成分のfloat型の数が昇順となるような、インスタンスを作ってみます。
 
let order2u = { new IComparer<int*float*int> with
                    member this.Compare(l,r) =
                      let (_,l2,_) = l 
                      let (_,r2,_) = r
                      if l2 > r2 then 1 //降順にするならここが-1
                      elif l2 = r2 then 0
                      else -1 //降順にするならここが1
                      }  
先にF#Interactiveにopen System.Collections.Genericを食わしておいてから、上を読み込ませると
val order2u : IComparer<int * float * int>
となります。
それではソートしてみます。//tはmutableであることにも、注意してください。
 
> t.Sort(order2u);;
val it : unit = ()
 
> t;;
val it : ResizeArray<int * float * int> =
  seq [(-3, -1.1, 6); (1, 0.1, 2); (-3, 2.0,-2); (3, 5.9, 5); ...]
  
それでは宿題です。第3成分のint型の数が昇順となるように、インスタンスを作ってtをソートしてみてください。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。