本日のTIL 今日は 前回 予告した通り Java の抽象クラスとインターフェイスについてまとめます。
抽象クラス abstract という修飾子をつけることで 抽象クラス を作ることができます。
特徴 オブジェクトを作成することができない new して作れないってこと。 抽象クラスの変数や配列は準備してサブクラスのオブジェクトをさすことはできる。 処理内容が定義されていないメソッド ( 抽象メソッド – abstract method )を持っている。 abstract というキーワードをつけてメソッドを定義すると抽象メソッドに。 サブクラスを拡張することができる。 ただし、 抽象クラスから継承した抽象メソッドの内容をサブクラスで定義、オーバーライドしなければならない 。 サブクラスは必ずその抽象クラスのメソッドを持っているので、まとめて簡単に扱える。 インターフェイス 宣言 こんな感じ↓
interface iVehicle { void show(); // 抽象メソッド } 特徴 interface を使って宣言する。 フィールドとメソッドを持つことができる。 コンストラクタは持たない。 フィールドは必ず初期化する。 メソッドの処理は定義しない。 メンバには何も修飾子をつけない。 何もつけなくても、フィールドには public static final, メソッドには abstract がついているのと同じことに。 つまりフィールドは絶対定数で、メソッドは抽象メソッド。 オブジェクトを作成することはできません。 変数・配列を宣言することはできる。 クラスと組み合わせて使うことになっている。 クラスと組み合わせることを インターフェイスを実装する という。 使い方 インターフェイスの実装 class <クラス名> implements <インターフェイス名> { /* hogehoge fugafuga piyopiyo */ } さて、このようなクラスを作ったら、インターフェイスのメソッドをすべて定義する という作業が必要になります。 インターフェイス型の配列は、そのインターフェイスを実装しているサブクラスのオブジェクトを指すことができます。インンターフェイスも、上で見た抽象kルアスと同じように サブクラスをまとめて扱うことができます 。
本日のTIL 今回は「やさしいJava」を読んで Java のクラスについて学んだ中で今まで意識できていなかった考え方や馴染みのなかった書き方、概念などについて書きます。
クラスの機能 カプセル化 カプセル化についてはもちろん Java を学び始める前もなるべく意識してコードを書いてきたので詳しくは書きませんが、全てのメソッドの先頭に public private とついているとわかりやすいなと思いました。 ( Ruby で private 以下が長くなって「結局これ private メソッドなの?」みたいになること、うーん、あるのか……?)
メソッドのオーバーロード Java では 同じクラスの中に、同じ名前を持つメソッドを複数定義すること ができ、これを メソッドのオーバーロード といいます。 ちなみに、コンストラクタもオーバーロードすることができます。
効果 似たような複数の処理を、1つのメソッド名を覚えて使うだけで自動的に型や個数に応じた処理が行われる。 似たような処理について同じメソッド名を利用することができる。 1つの名前が別々の働きを持つことを多様性というが、これが生まれる。 注意点 オーバーロードするメソッドは引数の型もしくは個数が異なってなければならない。 余談 Ruby にはないものですね ( そうですよね? ) 。 これができるのはやはり静的型言語の強みなのかなと思います。 今まで JS や Ruby しか書いていなかったので、同じ名前のメソッドを同じクラス内に定義するというとびっくりしますが、考えてみればとても便利ですね。 Ruby だと、個数の違いに対応するために引数にデフォルト値を入れたり配列やハッシュを引数にしたり、引数の型で処理を分けるためにメソッドの中で調べたりすると思いますが、 Java だとその必要がなくて、一つのメソッドが無駄に長くならなくて嬉しいですね!
インスタンス変数・インスタンスメソッド オブジェクトに関連づけられているフィールドをインスタンス変数 オブジェクトに関連づけられているメソッドをインスタンスメソッド と言います。
インスタンス変数・インスタンスメソッドはオブジェクトが作成された時にアクセスできるものです。
クラス変数・クラスメソッド クラスに関連づけられているフィールドを クラス変数 、メソッドを クラスメソッド と言います。 これらはインスタンス変数とは異なり、クラス全体に関連づけられます。 クラス全体で扱うデータを格納しておくフィールド がクラス変数、 クラス変数を出力するなど、 クラス全体に関わる処理を行う のがクラスメソッドです。 クラスメソッドはオブジェクトが作成されていなくても呼び出せます。 代表的なクラスメソッドとして main() メソッドがあります。
本日のTIL 前提として。 Java 書いたことないんじゃあ! Java どころか静的型言語をまともに書いたことがありませんでした。 今までやってきたのは JS ( 主にサーバーサイドNode.js ) と Ruby ( Rails ) でした。 しかもやってきたと言ってもたかだか一年間で、エンジニアとしてのバイトやインターンは複数の会社でやっていましたがまだまだひよっこです。 そんな私がマネーフォワードに入社するにあたり Java を書くことになって、インターン期間中は Java の勉強をしていました。
この記事を読むときは一応前提として上記のことを頭においていただければなと思います。
Java のコレクション Java には様々な種類のコレクションがあるのですが、そのうち私がこの一週間半で使ってみたコレクションについてまとめます。
配列 配列という言葉はお馴染みのものですが、Java の配列は私が知っている JS や Ruby の配列とは決定的に違うことが一つありました。 長さが変えられない ということです。
また、初期化の方法も少し馴染みのない感じでした。
// 例えばこんな感じとか int array[] = new int[5]; // こんな感じ int array[] = { 1, 2, 3, 4, 5 }; # 例えばこんな感じとか array = Array.new(5) # こんな感じ array = [1, 2, 3, 4, 5] array[] という書き方や { } で囲うのは新鮮だなあと感じました ( だからと言ってどうというわけでもないのですがw )。
03/30のTIL では早速本日のTIL ぶつかったこと Java を書く中で正規表現で文字の “[” や “]” にマッチさせたいと思って、頭の中でこんな感じに思い浮かべました。
Pattern.compile("[[]]"); いやいやこれじゃメタ文字の [] になっちゃうよと思い、実際にはこう書きました。
Pattern.compile("[\[\]]"); ただしこれは > Invalid escape sequence (valid ones are \b \t \n \f \r \” \’ \ )
と言われます。 「ん?じゃあエスケープしなくていいの?」と思い、最初に頭に思い浮かべたものを書くと、今度はコンパイルできました。 ところが、実行してみるとこう言われます。
Exception in thread “main” java.util.regex.PatternSyntaxException: Unclosed character class near index 3
解決法 結論としてはこうすれば動きます。
Pattern.compile("[\\[\\]]"); 自分なりに解説 [] のままでは文字ではなく正規表現のメタ文字として評価されてしまうというのは正しかったです。 ただ、ならば \ でエスケープして \[\] とすればいいかというとそれだけではダメです。 Java では文字列中で \ を表すには \ を用いてエスケープする必要があるからです。 結果として \\[\\] になります。 もちろん、[ ] に限らず、正規表現内でエスケープが必要な文字は全て、 正規表現のエスケープとしての \ と Java の文字列のエスケープとしての \ の二つが必要 です。