interface、staticメソッドと書いてありますが
java8で実装されたインタフェース内の静的関数の話ではないです。
こちらを期待された方はゴメンナサイ。
先日、アレ? って思ったことがあったのでメモ的な感じでのこしておきます。
public final class ArleneFamily {
public static final class Father {
public static String name() {
return "アイリーンのパパ";
}
public static String birthDay() {
return "3/2";
}
}
public static final class Mother {
public static String name() {
return "アイリーンのママ";
}
public static String birthDay() {
return "10/30";
}
}
}
public class Sample1 {
public static void main(String[] args) {
System.out.println(ArleneFamily.Father.name() + ":" + ArleneFamily.Father.birthDay());
System.out.println(ArleneFamily.Mother.name() + ":" + ArleneFamily.Mother.birthDay());
}
}
こんな感じの定数クラスがありまして・・・
アイリーン家構成クラス(ArleneFamily.java)と、それを表示するクラス(Sample1)になります。
実際にはアイリーン家以外にもたくさんの○○家構成クラスがある感じです。
既存仕様として各家それぞれの構成表示しかしてこなかったんですが
ブレット家もシンディ家もまとめて誕生日表示がしたい!!
というような事があり・・・
public class Sample2 {
public static void main(String[] args) {
System.out.println(ArleneFamily.Father.name() + ":" + ArleneFamily.Father.birthDay());
System.out.println(ArleneFamily.Mother.name() + ":" + ArleneFamily.Mother.birthDay());
System.out.println(BretFamily.Father.name() + ":" + ArleneFamily.Father.birthDay());
System.out.println(BretFamily.Mother.name() + ":" + ArleneFamily.Mother.birthDay());
・
・
・
}
こんな感じになったんですが、コレハナイダロ・・・
ということでインターフェースを付けて、
使う側は下記のような感じにしたいなぁと考えてみることに。
public static void main(String[] args) {
printBirthDay(~モヤモヤ~);
printBirthDay(~モヤモヤ~);
・
・
・
}
private static void printBirthDay(~モヤモヤ~) {
System.out.println(インターフェース.name() + ":" + インターフェース.birthDay());
}
早速、Humanインターフェースを作成して、
public interface Human {
public String name();
public String birthDay();
}
impl付与。
public final class ArleneFamily {
public static final class Father implement Human {
public static String name() {
return "アイリーンのパパ";
}
public static String birthDay() {
return "3/2";
}
}
public static final class Mother implement Human {
public static String name() {
return "アイリーンのママ";
}
public static String birthDay() {
return "10/30";
}
}
}
はい。エラーです。
メソッドの static を外せやゴルァと怒られました。
staticがoverrideできないのは静的だし分かるけど、
インターフェースの実装強要なら書けてもいいんじゃないかと思うんだけどなぁ
まぁ
I/Fを実装する際にoverrideアノテーション付けたり、総称型もクラスと一緒でextends指定だし、やっぱりstaticがoverrideできないのと根っこは一緒なのかなぁ
しゃーないのでメソッドからstaticを外します。
public final class ArleneFamily {
public static final class Father implement Human {
public String name() {
return "アイリーンのパパ";
}
public String birthDay() {
return "3/2";
}
}
public static final class Mother implement Human {
public String name() {
return "アイリーンのママ";
}
public String birthDay() {
return "10/30";
}
}
}
はい、今度は使用している部分でエラー。↓ここの部分
System.out.println(ArleneFamily.Father.name() + ":" +
インスタンス作成しろや!・・・ってまぁstatic外したんだからそうなるよね。
仕方ない、使用している側を直していくか・・・結構数あるし、影響範囲でかくなるなぁ
と思ったときにビビビっと閃きました!
public final class ArleneFamily {
public static final Human Father = new Human() {
@Override
public String name() {
return "アイリーンのパパ";
}
@Override
public String birthDay() {
return "3/2";
}
};
こんな感じにすれば使用側も触らなくてよくね?
やってみたら
案の定、これだと使用側もエラーにならず・・・↓ここの部分。うまく通る。
System.out.println(ArleneFamily.Father.name() + ":" +
さらにインスタンス生成という形でクラス構成が確定したので
モヤモヤ部分の書きっぷりも解消。
public static void main(String[] args) {
printBirthDay(ArleneFamily.Father);
printBirthDay(ArleneFamily.Mother);
・
・
・
}
private static void printBirthDay(Human human) {
System.out.println(human.name() + ":" + human.birthDay());
}
一応、もともとConstantクラスだったからnewされないように一応デフォルトコンストラクタをprivateにしておいてっと。
これで無事、当初の目的の改修を完了~~
さてやっと本題です。(笑)
上記でコンパイルが通るということは
もともとの内部クラス(Father)とHumanインターフェースを実装した変数(Father)
って共生できるのか?できたらどっちが優先されるのか?という疑問に・・・
public final class ArleneFamily {
public static final Human Father = new Human() {
@Override
public String name() {
return "アイリーンのパパ";
}
@Override
public String birthDay() {
return "3/2";
}
};
public static final class Father {
public static String name() {
return "アイリーンの父親";
}
public static String birthDay() {
return "11/12";
}
}
はい、共生できました。。
返却値を変えてどちらが実際に呼ばれるのか試してみる。
アイリーンのパパ:3/2
変数が優先されました。
いろいろと調べてみた結果
ココの6.4.2. Obscuring、6.5. Determining the Meaning of a Name
にちゃんと書いてありました。
変数は型より優先。型はパッケージより優先。
知らなかった・・・
まぁ現場じゃわざわざ同名にするなんてありえないしね。
今回いい機会で知れました。
ちなみにFamilyを例にしましたが、実際には商品系です。
名前を置き換えたらこんな感じに orz
なんか違和感が。
javaのチラ裏の話なので、見出しなしです。