ひしだまHPの更新履歴。 主にTRPGリプレイの元ネタ集、プログラミング技術メモと自作ソフト、好きなゲームや音楽です。
ひしだまの変更履歴
privateメンバーへアクセスする為のキャスト
kmizuさんのエラーの例の意味が最初分からなかった。
(lessThanというメソッド名なのに==で判定しているのがおかしいのかな?と思ったけど、そこは本題ではなかった)
cocoa_rutoさんのツイートで可視性に言及されていて、ようやく意味が分かった。
つまり、“自分を継承したサブクラス”として宣言した変数では、自分のprivateメンバーにアクセスできない。わざわざ自分自身にキャストしてやればアクセスできるようになる。
kmizuさんのソースでは、型TはFooを継承したサブクラスとなっている。(ジェネリクスのextends)
なので、Tの変数fooでは、FooのprivateメンバーであるaValueにアクセスできない(foo.aValueが不可視であり、コンパイルエラーになる)
うーん、こんな可視性の問題があったんだなぁ。Javaでもまだまだ知らない事が多い。
Javaの例をScalaに変換して説明してみる
Javaのオブジェクト指向っぽい説明の例を、Scalaに書き換えてScalaを説明してみる。
Scalaはオブジェクト指向と関数型が融合された言語なので、ベースとしてJavaと似たオブジェクト指向(クラス)が使える。
Javaのインターフェースは、Scalaではトレイトで書く。
trait 政党 {
def 政策を作成する() : 政策
}
defでメソッドを定義する。(Scalaは関数型言語でもあるが、クラスやトレイト内に定義するのは関数ではなくメソッド。場面に応じて、メソッドは関数に(自動的に)変換して使われる)
Javaとは違い(Pascalと似て)、メソッドの戻り値の型(や変数の型)はコロンで区切って後ろに書く。
抽象メソッドの宣言はabstractキーワードをつける必要は無く、メソッド本体を記述しないだけ。
また、可視性は、何も書かない場合はpublicになる。
世界に一つしか無い官僚機構は以下のような感じで書ける。
object 官僚 {
def 政策を実施する(s: 政党) : 結果 = {
try {
val dummy = s.政策を作成する()
} catch {
case e: Exception =>
}
new 天下り先()
}
}
(トップレベルに書かれた)objectは、シングルトンオブジェクトとなる。つまりnewしなくても自動的にVM内に1つだけインスタンスが作られる。
(トップレベルでなくクラス内に書かれたobjectはクラスをインスタンス化する際にそのインスタンス毎に作られる(staticの代わりではない)ので注意)
メソッド本体は、戻り型の指定の後ろに「=」を付けてその後ろに書く。
各文の末尾のセミコロンは省略可能。Scalaでは普通は書かない。
メソッドの戻り値としては、波括弧でくくられたブロックの一番最後の値が返る。したがって「return」は書かない。(Javaと違って、メソッド内の途中でreturnで抜けることは基本的にしない)
try〜catchの機能はJavaと同じだが、catch句の書き方がちょっと違う。(Scalaのmatch式の書き方に近い)
caseの「=>」の後ろに例外処理を書くのだが、官僚は握りつぶしている(何も処理しない)ので、例としては良くないな^^;
トレイトをミックスイン(「インターフェースを実装する」のと同じような意味)してクラスを書くには以下の様にする。
class 自党 extends 政党 {
override def 政策を作成する() : 政策 = new 我田引鉄()
}
class 共党 extends 政党 {
override def 政策を作成する() : 政策 = new 実現不可能な理想論()
}
メソッドをオーバーライドする際はoverrideを付ける。Javaでは@Overrideアノテーションだったが、Scalaでは言語内で規定されたキーワードとなっている。
(抽象メソッドをオーバーライドする際はoverrideを付けなくてもいい(付けないのが多数派だ)が、個人的には付けた方が良いと思っている。オーバーライドしていることが一目瞭然だし、親クラスのメソッド名を変えたときにコンパイルエラーになってくれるし)
メソッド本体が1つの式で収まる場合は、波括弧のブロックにする必要が無い。
(Scalaの構文としては、メソッド本体は1つの式を指定するだけ。複数の文を書きたい場合に波括弧のブロックを利用するという扱い)
インスタンスをnewで作ることはJavaと同じ。
ただし、コンストラクターの引数が無い場合は丸括弧も省略できる。
val 元祖自党 = new 自党()
var 亀下新党 = new 自党
var 石井新党 = new 自党
var 橋原新党 = new 自党
変数はvarまたはvalで定義する。
valは、Javaでのfinal変数と同じ。つまり、valで定義した変数には他の値を再代入することが出来ない。変数が別のインスタンスを指すことが出来ないというだけで、変数内のインスタンスの中の値が書き換えられないわけではない。Scala(関数型の考え方?)としては、インスタンス内が書き換えられないようにクラス(イミュータブルなクラス)を作るのが望ましい。
イミュータブルなクラスでは、インスタンス内の一部を書き換えたい場合は、書き換えずに新しいインスタンスを生成する形となる。
今回の政党の機能としては扱っていないが、政党間で党員の移動(自党から民党への移籍等)は非常に頻繁に起こるので、インスタンス内の党員の一覧は書き換え可能な方がやりやすいだろう。
(個人的には、現在のScalaがJavaVM上で動いている以上はインスタンスを大量に生成するのは効率が悪いので、大量に書き換えが発生しそうな用途ならミュータブルにした方がいいと思う。ぜひ、Scalaにはイミュータブルでも効率の良いScalaVMを作って欲しいw)
あと、自分は手続き型言語歴が長いので、変数へ「代入する」という言葉を使うが、Scalaでは「束縛する(bind?)」と言うのが正しいっぽい。
変数名やメソッド名などに値を束縛する(割り当てる・固定する)というニュアンスなんだと思う。
既存のクラスを継承したクラスは以下の様に書く。
class 民党 extends 自党
独自のメソッドやフィールドを定義しない場合は、クラス定義の波括弧が省略できる。
コンストラクターの引数で渡された値をフィールドに保持するだけの場合、クラス名の直後に引数(フィールド定義を兼ねる)を指定するような書き方が出来る。
class 委譲政党(protected val s: 政党) extends 政党 {
override def 政策を作成する() = s.政策を作成する() //他の政党に委譲する
}
val 公党 = new 委譲政党(元祖自党)
val 社党 = new 委譲政党(元祖自党)
メソッドの戻り値の型がメソッド本体から推測できる場合は、defの型の指定は省略することが出来る。
ちなみに、Javaと同じような書き方をすると、以下の様にくどくなる。
class 委譲政党 extends 政党 {
protected var s:政党 = null
def this(s: 政党) = {
this()
this.s = s
}
override def 政策を作成する() = s.政策を作成する() //他の政党に委譲する
}
Scalaのクラスでは基本コンストラクターというものが必ず出来る。クラス名の直後に引数を書くとそれが基本コンストラクターの引数となる(省略された場合は引数なしのコンストラクターとなる)。
それ以外のコンストラクター(補助コンストラクター)はthisという名前のメソッドを定義するような書き方をする。
上記のthisメソッドでは、先頭でthis()を呼び出しているが。def thisで作った補助コンストラクターは必ず(自分より前に定義された)他のコンストラクターを呼び出す必要がある。ここら辺はJavaのコンストラクターとは考え方が違うところ。
基本的にはJavaのオブジェクト指向で出来る事はScalaでも出来るが、Scala独自の考え方で異なっている部分もある。
Scalaの勉強としては、次のステップはList操作(ScalaではSeqというクラス)を勉強するのが良いと思う。関数型を生かした便利メソッドがいっぱい出てくるがw、foreachが基本でfilterやmap辺りがまず重要。
比喩でJavaのオブジェクト指向を説明してみる
オブジェクト指向の説明をするのに色々な比喩が用いられ(、実際のプログラミングと離れていて結局分かりにくいと批判され)ているが、敢えて例えてみたい。
例として、政党を考えてみる。(以下、政党名や変数名はてきとーに架空のものを使用)
まず、共通のものとして「政党」を定義する。Javaで書くとこんな感じ。
public interface 政党 {
public abstract 政策 政策を作成する();
}
「政策を作成する」というメソッドを持つインターフェースである。
インターフェースは「こういう処理を呼び出せる」というメソッド一覧を定義するもの。
実際の処理(ここでは「政策の中身」)は規定せず、「政党であれば政策を作成する機能を持つ」ということだけを定義している。
abstractは「抽象」と訳されている。実際の処理を書かないメソッドは抽象メソッドと呼ばれる。
(なお、インターフェースの抽象メソッドではabstractキーワードは省略することが出来る)
(抽象メソッドを持つクラスは抽象クラスと呼ばれる。インターフェースは特殊な抽象クラスとも言える)
このようにしておくと、例えば政策を実施する官僚クラスからは以下のような感じで政党から政策を取得することが出来る。
private class 官僚 {
public 結果 政策を実施する(政党 s) {
try {
政策 dummy = s.政策を作成する();
} catch(Exception e) {
}
return new 天下り先();
}
}
実体がどの政党であるかに関わらず、メソッドを呼び出すように記述できる。これがオブジェクト指向(インターフェースを用いたプログラミング)の優れた点である。
なお、try〜catchは例外(正常な結果でない出来事)が起きたときにそれを受け止めて何らかの処理を行う為のもの。今回はcatch句に何も書いていないが、こういうのは「例外を握り潰す」と言われ、良くないコーディングの典型である。(例外は「都合の悪い事」ではなく「発生しうる事」なので、それに応じた処理を行う必要がある。少なくとも、ログ出力などを行い、外部の人(運用者)に見えるようにすべきである)
そして、実際の個々の政党クラスは“政党インターフェース”を実装することになる。「実装」とは、具体的な処理を記述することである。
(具体的に処理が書かれているクラスを、(抽象クラスに対して)具象(ぐしょう)クラスと呼ぶ)
例えば「自分が良ければ他人や将来の世代のことなんかどうでもいい党(以下、自党)」や「共に生産性を上げようなどと人類には不可能なことを言う党(以下、共党)」は以下のように書ける。
public class 自党 implements 政党 {
@Override
public 政策 政策を作成する() {
return new 我田引鉄();
}
}
public class 共党 implements 政党 {
@Override
public 政策 政策を作成する() {
return new 実現不可能な理想論();
}
}
継承元クラスに存在するメソッドに自分の処理を記述することを「オーバーライド(上書き)する」と言う。オーバーライドされたメソッドには@Overrideというアノテーションを付ける。
クラスの定義は、処理内容が記述されているだけであり、プログラム内で使う際には「インスタンス」を作る必要がある。インスタンスとは、いわば「処理を行う“中の人”」である。
インスタンスは「new」を使って作成する。以下の様になる。
政党 元祖自党 = new 自党();
政党 亀下新党 = new 自党();
政党 石井新党 = new 自党();
政党 橋原新党 = new 自党();
これらは、インスタンス(中の人)は違うが、クラスは同じなので実施する処理内容も全く同じである。
なお、変数の宣言は、実際のクラス名でなく、インターフェース名ですべき。そうすれば、後からnewするクラスをとっかえひっかえしても後続のプログラムは影響を受けない。
既存のクラスを継承して新しいクラスを作ることも出来る。
例えば、自党を継承した「民の為と称して好き勝手やる党(以下、民党)」は以下の様になる。
public class 民党 extends 自党 {
}
継承元と処理が同じ場合は、特に処理(メソッド)を書く必要は無い。
政党 小沢自党 = new 民党();
他の具象クラスを直接継承(extends)するのではなく、別インスタンスのメソッドを呼び出すような構造も作れる。
こういう仕組みを「委譲」と言う。
public class 委譲政党 extends 政党 {
protected 政党 s;
public 委譲政党(政党 s) { //コンストラクター
this.s = s;
}
@Override
public 政策 政策を作成する() {
return s.政策を作成する(); //他の政党に委譲する(他の政党の政策をそのまま使う)
}
}
コンストラクターは、インスタンスを作る際に引数を受け取ったりそのクラス独自の初期化を行ったりするもの。
コンストラクターで引数を受け取ってフィールド(クラス内で共通に使える変数)に保持するのは常套手段。
フィールド(「フィールド変数」という呼び方は間違い)とローカル変数で同じ変数名を使うことが出来る。同じ場所で使う場合、区別できるよう、フィールドには「this.」を付ける。
(同じ名前を付けることによって別変数にアクセスできなくなることをシャドーイングと言う)
引数つきのコンストラクターを使ってインスタンスを作る場合は、newするときに引数を渡す必要がある。
政党 公党 = new 委譲政党(元祖自党);
政党 社党 = new 委譲政党(元祖自党);
全然関係ないですが、つい最近、虚構新聞に釣られる人が出て話題になってましたね。
自分も虚構新聞には何度か騙されて^^;楽しませていただいていますがw、情報が正しいのか、どういう意図で書かれているのか・信じるのかは読み手が汲み取れるようにならないといけませんね。騙そうとする人(宗教や新聞テレビのプロパガンダ等)は、「嘘」と書かずに嘘をついたり誘導したりするので。(虚構新聞は虚構と書いてくれているので良心的w)
それがネットリテラシー、いやネットに限らずリテラシーとして必要なんでしょう、現代人には。
騙す方が悪いとは思いますが、犯罪者に倫理観を求めるのは不可能なので。
Sqoopで留意すべき事
Sqoopを使う上でこれは注意した方がいいんじゃないかな〜と思った点をつらつらと書いてみた。
SqoopはRDBに対してデータ転送する事に特化しているだけあって、「さすが色々考慮されているなー」と思うところと「やっぱこれはしょーがないよねー」というところ(データの偏りとか)がある^^;
あと、うっかり忘れていたダイレクトモードもちょびっと試してみた。
MySQLとPostgreSQLで機能が違いすぎ^^;
一番肝心な速度はどうなんだろうなー、仮想分散環境しか持ってないからなー。
Sqoop PostgreSQL
SqoopでPostgreSQLとのデータ転送を試してみた。
MySQLで試して上手くいっているんだから大丈夫だろう…と思いきや、exportで落ちた(汗)
落ちた原因は、PostgreSQLのバージョンが古かった所為。
Sqoopのexportでは、「insert into テーブル values(…), (…), (…)」という様に、insert文で値の組を複数記述したものを使っている。
PostgreSQL8.1はこの構文に対応していない為、エラーになる。
PostgreSQL8.2以降やMySQLは対応しているので大丈夫。
つーか、PostgreSQL8のマイナーバージョン違いでそんな大きな違いがあると思ってなかったよorz
CentOSのyum install postgresql-serverだと8.1が入るから、そのまま使っていたらこのざま…。8.4をインストールするのにyum install postgresql84-serverって、分かり易いっちゃ分かり易いけどさぁ^^;
PostgreSQL8のインストール方法
超久しぶりにPostgreSQLのメモを更新。PostgreSQL8.4をCentOSにインストールする方法。
(今までのインストール方法はPostgreSQL7.2が対象だったので、専用のページを作ってそちらに移した)
どれくらい久しぶりかって、最終更新が2003年だったから9年ぶりだよ!!
2003年と言えば、自分がJavaを始めた年でもある。
つまり、Java+PostgreSQLのシステムの担当になったからなんだけど(笑)
(しかもこれが自分が経験したナンバー1のデスマーチで(爆))
Struts1は出ていたような気がするが、Eclipse2はまだ出ていなかったはず。本当にテキストエディターでJavaのソースを書いてたからなぁ…。
いやぁ、Eclipseの生産性はすごいわ。
Sqoop MySQL
Apache Sqoopをちょっとだけ触ってみた。
コマンドラインの基本的なオプションだけでもけっこうある。
おかげでCSVファイルとして扱う為の基本的な機能は充実している。
また、SequenceFileとしても扱うことが出来るのはさすが。
本当は分散環境で並列してデータ転送してみないと本来の動作の検証にはならない訳だが、とりあえずはここまででいいやw
『HADOOP HACKS』
『HADOOP HACKS』に一通り目を通した!
(Mahoutは関連知識不足なので飛ばしたけど…)
色々な話題が詰まっているので、基本的には全部読むのではなくて興味のある部分だけ読むタイプの本かな。
基礎は知っている前提で書かれているので、まどろっこしい入門向け説明でページを使わず、一気に本筋に入るのが素晴らしいw
掲載されているソースコードについては抜粋だし(本筋とは関係ないところだがバグもあったりするし)、実際に使いたいと思ったら、サイト(http://sg.sg/hhacks)で公開されているソースを見た方が良さそう。
(自分がソースコードレビューをするんだったらHashMapの定石…とかforeachを使った方がーとかnew Integerを使うなーとか言いたい部分もあるけどw、Hadoopとは関係ないから別にいい)
以下、個別の章の感想。
- システム構築/運用
- マスターノードのHA化は『Hadoop徹底入門』にも出ていたと思うけど、実際にやろうとしたらかなり大変らしいので、情報は多い方がいいよね
- SqoopはHDFSと外部とのデータ転送で注目されていると思うんだけど、あまり知らなかったので、載っていて嬉しい。SqoopではOracleのテーブル名を大文字で書かないといけないなんて、絶対ハマりそう
- アプリケーション開発
- 自分が「HashMapを使う方式」って呼んでたやつは、InMapperCombinerって名前が付いていたのか!
- DistributedCache(分散キャッシュ)とかCombineFileInputFormatとかMapサイドジョインとかReduceサイドジョインとか、自分でMapReduce書いて実行性能を出そうとしたら必要そう
(これを自前でやる気はしないけど^^;、AsakusaFWは内部でこういうのを駆使しているはず) - HBase
- 「カラムファミリー」とか何の説明も無しに使われているのが新鮮w(HBaseの入門だと、その辺りから入るから)
- バルクロードやHFileOutputFormat(MapReduceでHBaseにデータを入れる方法)やpre-splitテーブルの作成など、実際にHBaseを使う上で超重要そう
- Hive
- 性能面の話として、いきなりHiveで出来ない事が並んでいるのがすごいw
(これはHadoopを基盤としている以上、HiveもPigもAsakusaFWも同じだけど) - HiveQLはSQLに似ていると言われるが、違いを色々挙げているのが素晴らしい。知らない点が多かった
- Pig
- LoadFunc・Storage・UDFの作り方とか、他の章と比べると当たり前の内容が多かったなぁ
(Storageの作り方をググろうとすると、日本語の情報では自分のページくらいしか出ないので、もしかすると当たり前ではないのかもしれないが^^;) - PigをJavaから呼び出せるらしいという事は聞いたことがあったが、実際にやっている例は初めて見た
- ZooKeeper
- ZooKeeperのリーダー選択の仕組みやアクセス制御(ACL)・tickTime等、内部構造について説明されている
- znodeの操作とか分散並列キューのサンプルが載っている
- ZooKeeperへアクセスするツールがそんなに色々あるとは知らなかった
(Eclipse・REST・FUSE)
HBase TableOutputFormatの危険性
『HADOOP HACKS』のHBaseの章を読んでいると、HFileOutputFormatの使い方が載っていた。
それで、先日@ueshinさんから教えていただいたTableOutputFormatの危険性について思い出したので、メモ。
自分はTableOutputFormatしか使ったことが無いが(しかもサンプルレベルのみ)、TableOutputFormatはいわゆるロールバックが出来ないから危険ということらしい。
HFileOutputFormatを使ってHFileを作り、それをHBaseへバルクロードした方がいいそうだ。
HFileOutputFormatの使い方やバルクロードの方法は『HADOOP HACKS』に載っているぞw
(Windows7マシンに切り替えてからHBaseの環境を作っていないので、自分では試してない^^;)
Play2.0 Eclipse設定作成時にソースを添付する方法
ueshinさんがTwitterでeclipsifyにwith-source=trueという便利なものがあるとつぶやいていたので、ほほう!と思って試してみたら、上手くいかなかった(爆)
色々教えていただいた結果、とりあえず何とかする手順は分かったので、メモ。
…それにしても、こんなにハマるとは思わなかったなぁ(苦笑)
| « 前ページ |

