vim script で、クラスっぽい定義

まぁこの手のネタは、あちこちで語り尽くされているとは思うんですが。
特に深くつっこむつもりはなかったんですが、書き始めたら止まらなくなっちまった。
vim script にはクラスがないんですが、辞書に関数が定義できるので、クラスオブジェクトっぽく記述することが出来ます。

[ソース]

" クラスオブジェクトのファクトリ関数
function! s:class_animal(name, sound)
    
    " 辞書をクラスオブジェクトとして使用する
    let self =  {}
    
    " プロパティ
    let self.name = a:name
    let self.sound  = a:sound
    
    " メソッド
    function! self.get_name()
        return self.name
    endfunction

    function! self.get_sound()
        return self.sound
    endfunction
    
    function! self.disp_name()
        echo "name is ".self.get_name()
    endfunction

    function! self.disp_sound()
        echo self.get_sound()
    endfunction
    
    " 定義した辞書を返す
    return self
endfunction

" ダック・タイピング的なもの
function! s:disp_name(animal)
    call a:animal.disp_name()
endfunction

function! s:disp_sound(animal)
    call a:animal.disp_sound()
endfunction

function! s:disp(animal)
    call s:disp_name(a:animal)
    call s:disp_sound(a:animal)
endfunction

" オブジェクトの生成
let dog  = s:class_animal("dog", "わんわん")
let cat  = s:class_animal("cat", "にゃー")
let duck = s:class_animal("duck", "がーがー")

call s:disp(dog)
call s:disp(cat)
call s:disp(duck)

let ikamusume = s:class_animal("イカ娘", "ゲソゲソー")

" ikamusume オブジェクトに対してオーバーライド
function! ikamusume.disp_name()
    echo self.get_name()."でゲソ!"
endfunction

call s:disp(ikamusume)


" class_animal から継承して拡張する
function! s:class_human(name, sound, level)
    " class_animal を代入(継承っぽい感じで)
    let self = s:class_animal(a:name, a:sound)
    " 基底クラスの呼び出し用変数
    let self.base = deepcopy(self)

    " プロパティ
    let self.level = a:level
    
    " メソッド
    function! self.get_level()
        return self.level
    endfunction
    
    " オーバーライド
    function! self.disp_name()
        " 基底クラスの呼び出し
        call call(self.base.disp_name, [], self)
        echo "level:".string(self.get_level())
    endfunction
    
    return self
endfunction

let kamijo = s:class_human("上条当麻", "そげぶ!", 0)
let misaka = s:class_human("御坂美琴", "ビリビリ", 5)

call s:disp(kamijo)
call s:disp(misaka)

[出力]

name is dog
わんわん
name is cat
にゃー
name is duck
がーがー
イカ娘でゲソ!
ゲソゲソー
name is 上条当麻
level:0
そげぶ!
name is 御坂美琴
level:5
ビリビリ

なるべくシンプルに書こうと思ったらこんな感じになりました。若干、基底クラスの呼び出しがめんどくさいんですけども。
本当はコンストラクタも書こうと思ったんですが、呼び出しが複雑になりそうなので止めました。
初期化用のコンストラクタは、init メソッドみたいなのを書くのが無難な気がしますね。
まぁ全体的に見ればそれっぽく見える…かな。
アクセシビリティが設定できないので、完全なカプセル化は無理な感じがする。
あとクラス名とかを文字列で保持する必要があるのかは微妙な所。
んーこれ以上改良の余地はあるのか否か。