DoJa エミュレータでオプションとなっている API を使うと例外が出る

少し前にはまった。DoJa エミュレータのデフォルトではライブラリが不足しているので呼び出そうとすると RuntimeError になる。エミュレータ上で正しく動作させるには micro3d_v2_32.dll というファイルを DoJa の bin フォルダにいれてやる必要がある。
<http://www.mascotcapsule.com/toolkit/docomo/>
– micro3d_v2_32.dll の配布元。
– 追記 2005-12-19: ダウンロード場所がわかりにくい気がするので捕捉。現在、
DoJa 2.5oe/3.0/3.5 の Tools -> DLL micro3d_v32.dll でダウンロード可能。

DoJa プロジェクトの最小構成要素

Eclipse + iαppliTool for DoJa-X.X を使って開発しているのだが、
Eclipse の DoJa プラグインを使わずに新規プロジェクトを作るときに何が必要なのか毎度忘れるのでメモ。(DoJa 4.0 で確認)
 注: prefix の + はディレクトリ, – はファイルをあらわす事にする。
 +projectname – プロジェクト名と同じディレクトリ名
   -projectname – プロジェクト名と同名のファイル(拡張子なし)
   -projectname.properties – プロジェクト名と同名のファイル(拡張子 .properties)。 なくても動作はするが、これがないとファイル配置など設定が保存されない。
   +src – ソースフォルダ(*.java)
   +bin
     -projectname.jam – プロジェクト名.jam
   +res – リソースディレクトリ(resource:///filepath でのアクセス用)
Eclipse で作業する時は、リリースディレクトリを bin ではなく classes 等にすると干渉しない。また Eclipse で必要な設定は次の通り。
 
– リリースディレクトリを bin でなく classes にする。
  任意。DoJa との干渉を防ぐため
– JDK のコンパイラ互換性関係のオプションをバージョン 1.1 に近づける。
  任意。DoJa の動作する J2ME は JDK1.1 相当のため, Eclipse で通るものが DoJa のビルドでエラーになってしまったりする。そのためできるだけバージョンを下げておくのが望ましい。
– Java のビルドパスに DoJa のライブラリ(classes.zip, doja_classes.zip)を追加しておく。
  必須。DoJa をインストールすると DoJa のインストールディレクトリの /lib 以下にあるもの。
lib/profile の中のものは旧バージョンのライブラリ。

yield

– 処理を場合に応じて自由に変えられる。スマートになった Visitor パターンみたいなものかなぁ..
イテレーションを Iterator パターンなしでできる(内部で Iterator パターンを使って外には each メソッドを公開する等)。

class Iterator
  @values
  @nIndex
  
  def initialize(*values)
    @values = values.dup
    @nIndex = 0
  end
  
  def each
    yield(getNext) while hasNext
  end
  
  def hasNext
    return @nIndex < @values.size
  end
   
  private :hasNext
   
  def getNext
    throw RangeError.new(“no element for next”) if !hasNext
    
    res = @values[@nIndex]
    @nIndex += 1
    return res
  end
  
  private :getNext
end
 
iterator = Iterator.new(0,1,2,3,4)
iterator.each{ |i|
  print( i * 2, “, ” )
}
# result:
# 0, 2, 4, 6, 8,
#

この例はそのまま [0,1,2,3,4].each{|i| … } とした時の動作と同じだけど、マスターデータが膨大になりうる時などは自分で yield するメソッドを実装するとコスト削減になってよい。
 
参考:
<http://www.ruby-lang.org/ja/man/?cmd=view;name=%A5%E1%A5%BD%A5%C3%A5
%C9%B8%C6%A4%D3%BD%D0%A4%B7#yield
>

可変長引数メソッド

def foo ( *args )

のように引数を一つだけ、最初に * をつけて定義すると、引数を配列(Array インスタンス)として扱える。

  def main(* args)
    print args.size, ” arguments: “
    args.each { |i|
      print i, “, “
    }
    print “\n”
  end
  
  main(1,2,3)
  main(“foo”, 2)
  main()
# result:
# 3 arguments: 1, 2, 3,
# 2 arguments: foo, 2,
# 0 arguments:
#

アクセス制限

def foo
end
private :foo
 
def boo
end
protected :foo
 
def woo
end
public :woo

 : とメソッド名前の間には空白をはさんではいけない。
 
ちなみに, private としたメソッドを子クラスで再定義すると, 上書きされてしまうので注意が必要。

class Parent
    def foo(arg)
       print “parent “, arg, “\n”
    end
    private :foo
    def woo
      foo(“hello”)
    end
end
 
class Child < Parent
    def foo
       print “child\n”
    end
end
 
Child.new.woo
 
# result:
# in `foo’: wrong number of arguments (1 for 0) (ArgumentError)

 
参考:
<http://www.ruby-lang.org/ja/man/?cmd=view;name=%A5%AF%A5%E9%A5%B9%A1
%BF%A5%E1%A5%BD%A5%C3%A5%C9%A4%CE%C4%EA%B5%C1#a.b8.c6.a4.d3.bd.d0.a4.
b7.c0.a9.b8.c2
>

クラス定義基本(コンストラクタ, 継承, 自己参照, 親メソッド呼び出し)

– initialize メソッドがコンストラクタになる。

class Foo
  def initialize(arg)
    print “Hello, ” + arg + “!”
  end
end
 
Foo.new(“world”)
# result:
# Hello, world!

 
– 継承は “<"。シェルで使うような取り込むイメージ

class Parent
end
 
class Child < Parent
end

 
– 親クラスメソッド呼び出しはオーバーライドするメソッドで super とする。

class Parent
    def foo(arg)
       print “parent “, arg, “\n”
    end
end
 
class Child < Parent
    def foo(arg)
       print “child\n”
       super(arg)
    end
    
end
 
Child.new.foo(“abc”)
#
# result:
# child
# parent abc
#

– メソッドのオーバーロードはできない
オーバーロードしようとすると最後の定義のみ有効になり、それ以外の呼び出しでは引数の数が違うというエラーが出る。

wrong number of arguments (1 for 0) (ArgumentError)

 
– 自己参照は this ではなく self

class A
  attr_reader :name # 必須
  
  def initialize
    @name = “John”;
  end
  
  def foo
    print self.name
  end
end
 
A.new.foo
#
# result:
# John

self での参照はクラス外部からの参照と同等となるのでアクセス制限に注意!!
 
– 多重継承はモジュールに対してのみ可能
<http://www.ruby-lang.org/ja/man/?cmd=view;name=Module>
include で疑似的に実装する。

class Parent
end
 
module SubParent # module で宣言されていることに注意
  def foo
  end
end
 
module SubParent2 # module で宣言されていることに注意
  include SubParent # module -> module の継承
  def woo
  end
end
 
class Child < Parent # class -> class の継承
    include SubParent # module -> class の(多重)継承
    include SubParent2 # module -> class の(多重)継承
end

ちゃんと SubParent, SubParent2 の子として認識されるのでまぁ安心して使える。
多重にするには親を module にしないとだめって事で制限があるので、 Java でいうところの interface に近い使い方になるのかな。
 
– 委譲 (delegate)
デリゲート用のライブラリがあった。
<http://www.ruby-lang.org/ja/man/?cmd=view;name=delegate.rb>
でもデリゲートしてるのに宣言時点で親クラスにならないとだめとか微妙なような..
include delegate(Array)
みたいな使い方ならいいのにな。

アクセサの定義の仕方

その1

attr_accessor :attr1, :attr2, :attr3# read/write
attr_reader :attr3, :attr4 # read-only
attr_writer :attr5 # write-only

 : を使う宣言式共通の注意事項だが

attr_accessor: attr1

などとするとエラーになるので注意。
 : は先頭の宣言にかかるのではなく各プロパティにかかるので、各プロパティごとに空白を挟まず先頭に : をつけないといけない。
 @ をつけた同名のインスタンス変数に対してのアクセサとなる。
 
その2

# reader
def attr1
  return @attr1
end
# writer
def attr1= (arg)
  @attr1 = arg
end

任意の実装をしたい場合はこちらを使う。
 
毎回忘れるのでメモ。公式ドキュメント読みづらいっす。
参考:
<http://www.ruby-lang.org/ja/man/?cmd=view;name=FAQ%3A%3A%A5%E1%A5%BD
%A5%C3%A5%C9
>
– Ruby 公式ドキュメント -> FAQ -> 5. メソッド