まず、オブジェクト指向(以下 OOP)が何たるかを学ぶべきです。
手前味噌ですが、こちらを参考にしてください。
簡単に言えば『データと処理を一まとめにしたオブジェクト』を中心にみる発想です。
継承は『オブジェクトだけが知っている状態』にするためのものです。
なので、has-a関係ではなく、is-a関係である必要があります。
今回は
Java
1Way way = new Way();
となっていますが、
これは
『Wayクラスで生成し、Wayクラスのオブジェクトとして見なす』
と言った感じでしょうか。
今回はポリモーフィズムを表現したいようなので、
Java
1Way way = new Way();
を
Java
1Way way = new Newway();
のように、
『子で生成して、親で保持』してみては?
[追記1]
OOPの本質は『オブジェクトに管理や処理を任せる』にあると思います。
上記で挙げたページのような感じで。
で、ポリモーフィズムは『継承しているから』とかそういうのではなく、
『オブジェクトだけが知っている』という状態です。
たとえば、
ユーザ入力によって "+" が入力されたら足し算クラス、"-" が入力されたら引き算クラス……というそれぞれのクラスを生成して処理するとします。
単純に考えれば、
Java
1String user; // これに "+" とかが入っているとする
2
3Addition a; // 足し算クラス
4Sub s; // 引き算クラス
5Mult m; // 掛け算クラス
6
7// ユーザ入力によって生成するクラスを決定する
8if( user.equals( "+" ) ){
9 a = new Addition( 10 );
10}else if( user.equals( "-" ) ){
11 s = new Sub( 10 );
12}else if( user.equals( "*" ) ){
13 m = new Multi( 10 );
14}
15
16int ans = 0;
17
18// 処理!
19if( user.equals( "+" ) ){
20 ans = a.calc( 2 );
21}else if( user.equals( "-" ) ){
22 ans = s.calc( 2 );
23}else ...
のように、生成時はもちろん、処理時(メソッドを使っての処理とか) もif文で分岐させないといけません。
でも考えてみてください。
『オブジェクトだけが対象データと処理方法を知っている』のだから、『オブジェクトに任せればいい』となりませんか?
そう、これがポリモーフィズム。
オーバーライドするなりして、『オブジェクトが知っている』状態にする。
こうすることで、Calculatorクラスを継承(あるいはインターフェースを実装でもいい) とすれば、
Java
1String user; // これに "+" とかが入っているとする
2
3Calculator c; // 計算系オブジェクト
4
5// ユーザ入力によって生成するクラスを決定する
6if( user.equals( "+" ) ){
7 c = new Addition( 10 );
8}else if( user.equals( "-" ) ){
9 c = new Sub( 10 );
10}else if( user.equals( "*" ) ){
11 c = new Multi( 10 );
12}
13
14/*
15 処理!!!!
16 オブジェクトが対象データと処理方法を知っているため、
17 処理や管理をオブジェクトに任せる
18*/
19int ans = c.calc( 2 );
と出来ます。
こうすることで、cは new で生成されたクラスのオブジェクトなので、オブジェクト自身が
対象データと処理方法を知っています。
なので、『オブジェクトに任せる』ための機能というか、そういうのがポリモーフィズムです。
(オブジェクトそれぞれが処理方法を知っているため、『多様性』ができる)
クラスはこのオブジェクトのデータ構造(どういうデータや処理を持っているかとか)をコンパイラとかに提示するためのものです。
つまり、『オブジェクト指向の本質』である、『オブジェクト自身が対象データと処理方法を知っている』ことにより、『オブジェクトに任せる発想』というのがオブジェクト指向です。
そしてそれらを表現するためにクラスやら継承やらポリモーフィズムやらカプセル化やらがあるのです。
参考文献(サイト): よい子のC++(オブジェクト指向完全理解)
参考サイトはC++ですが、Javaとかでも発想自体は一緒です。