アクセス制限

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. メソッド

HTML のような画像敷き詰めをするメソッド

– ゲームを作っていると背景などで同じ画像をタイル状に張る処理をよくやるのでメソッド化してみた。なかなか便利。とりあえず DoJa 用だが、ImageObserver を渡してやる部分をくっつければすぐに AWT 用に移植できるはず。

    /**
     * イメージを指定範囲に敷き詰める.
     *
     * @see Graphics#drawImage(com.nttdocomo.ui.Image, int, int)
     * @see Graphics#fillRect(int, int, int, int)
     *
     * @param g 敷き詰め先
     * @param img 敷き詰める画像
     * @param x 敷き詰め先左上 X 座標
     * @param y 敷き詰め先左上 Y 座標
     * @param w 敷き詰め先の幅
     * @param h 敷き詰め先の高さ
     * @author hiro.I
     * @since 2005-10-20 18:12:31
     */
    public static final void fillImage(Graphics g, Image img, int x, int y,
            int w, int h) {
        final boolean bHasHorizonalFraction = w % img.getWidth() > 0;
        final boolean bHasVerticalFraction = h % img.getHeight() > 0;
        final int COLS = w / img.getWidth() + (bHasHorizonalFraction ? 1 : 0);
        final int ROWS = h / img.getHeight() + (bHasVerticalFraction ? 1 : 0);
        for (int i = 0; i < ROWS; i++) {
            final int ty = y + i * img.getHeight();
            final int th = (i == ROWS – 1 && bHasVerticalFraction ? h
                    % img.getHeight() : img.getHeight());
            for (int k = 0; k < COLS; k++) {
                final int tx = x + k * img.getWidth();
                final int tw = (k == COLS – 1 && bHasHorizonalFraction ? w
                        % img.getWidth() : img.getWidth());
                g.drawImage(img, tx, ty, 0, 0, tw, th);
            }
        }

    }

頑健な Java プログラムの書き方

<http://www.alles.or.jp/~torutk/oojava/codingStandard/
writingrobustjavacode.html
>
– Writing Robust Java Code(2000.1.15) の邦訳版.
 
改めてこういうものを読んで、コーディング習慣の曖昧な部分を直していこうと思う。
個人的によくやるのは、

final Set listCustomers;
final Set customerList;

とかを曖昧な基準で使ってしまう。(前者はハンガリアンの流れのつもり、後者は英語の語順)
 
複数の単語から成る変数名の場合にどういう順序にするか、という点が曖昧だったが、ハンガリアン記法で定義されていない型に対してはやは

jvim での文字コード明示読み込み

jvim がファイルの文字コードを誤って解釈してくれた時や新規作成の時は文字コード明示をするとよい。

jvim -k s foo.txt

“-k” オプションで一文字で文字コードを指定する。

SJIS: s
EUC: e
UTF-8: t

など。その他 u とかもあるけど忘れた。
 
忘れていたのでメモしとく。

Cygwin でルートディレクトリが違う場合の対処

別の場所にコピーした Cygwin を実行しようとすると /tmp がないというエラーが出る。
これはルートディレクトリが適切にマウントされてないのが原因なので…

mount

で現在のマウント状況を確認し、/ が変なところにマウントされていた場合は

umount /

でアンマウント

mount -b c:/cygwin /

などとして適切な場所に再マウントする。このときついでにシンボリックリンク
が違う場所を指しているせいで色々発生してる場合もあるのでエラーを確認
しつつ適宜修正しておく。

JSTL でタグ属性に EL 式を書くとエラー

<c:forEach var=”org” items=”${organizations}”> 〜 </c:forEach>

の ${organization} など, タグの属性に EL 式を書くと

According to TLD or attribute directive in tag file, attribute items does not accept any expressions
(TLD やタグファイルの属性ディレクティヴによると、items 属性では式を使ってはいけないことになってますよ)

と怒られた(メッセージに従って EL 式を外すと通る)。何でだろうと悩んでいたら、
<%@taglib%> の uri によって参照しているバージョンが違うようで

<%@taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

としていたのを

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

に変更したら何事もなく動作した。ちなみに環境は
Apache Tomcat/5.5.9 + Jakarta Standard 1.1 Taglib/1.1.2 で、
JSTL については jstl.jar, standard.jar を WEB-INF/lib に入れたのと、
<%@taglib%> を宣言した以外は何もしていない。
どちらかでしか動作しないと思い込んでいたために気づくのが遅れ、これで
2 時間のロス。

Tomcat で Filter を使う例(IPアドレスによるアクセス制限)

<http://www.jajakarta.org/kvasir/bbs/technical/688?expand=true>
jakarta.org: Ja-Jakarta Project 掲示板 -> Tomcatでの特定のディレクトリに
対してのアクセス制限の方法
より転載(一部改変).
フィルタの実装の仕方、web.xml のパラメータの取得の仕方が分かるし、実用的。
web.xmlの設定:

<!– ローカルネットワークからだけのアクセス許可–>
<filter>
<filter-name>Allow Local Network Access</filter-name>
<filter-class>IpAddressFilter</filter-class>
<init-param>
<param-name>allowIP</param-name>
<param-value>192.168.0.</param-value>
</init-param>
</filter>
 
<filter-mapping>
<filter-name>Allow Local Network Access</filter-name>
<url-pattern>/pages/manage/*</url-pattern>
</filter-mapping>

 
IpAddressFilter.java:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class IpAddressFilter implements Filter {

private FilterConfig config;
private String allow_ip;

/**
* パスに対してアクセス制限を行う
*
*/
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final String ip_address = ((HttpServletRequest) request).getRemoteAddr();

if (!ip_address.startsWith(allow_ip)) {
((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN);
}
else {
chain.doFilter(request, response);
}
}

public final void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
this.allow_ip = config.getInitParameter(“allowIP”);
}

public final void destroy() {
this.config = null;
this.allow_ip = null;
}
}

その他参考:
– Java で Hello World
<http://www.hellohiro.com/filter.htm>