2012-02-20 12 views
0

私はOOPの新人です。だから、クラスがいつ別のクラスかについて愚かな質問があります。extendsここでOOP Java:子クラスを親クラスに戻すことはできますか?

私の例:

public class Test { 
    public Monitor getMonitor(){ 
     return new LCD(); 
    } 

    class LCD extends Monitor { NO-ERROR 
    class LCD {     ERROR at line `return new LCD` 
     //some other method or function not in Monitor Class. Example: 
     boolean isSamsung; 
     public LCD whatkindLCD(){   
     }  
    } 
} 

私は上記のコードのための1つの質問があります:LCDMonitorから延長され、LCDがモニターにはないいくつかの他のプロパティ/メソッドを持っているので。だから、LCDMonitorの子ですか?

これは、「大きなボックス」を「小さなボックス」に配置しようとしていることを意味します。ですから、私がreturn new LCDになったとき、Eclipseはclass LCD {を使ったときのようにエラーに気付かないのです。

感謝:)

+0

エラーメッセージは何ですか? –

+0

いいえ、モニターが戻ったらキャストしてください。 –

+2

@TedHopp Eclipseで、「LCDからMonitorクラスに変換できません」 – hqt

答えて

1

「継承は」関係として継承を理解します。ここでは初心者の間に継承を理解するのに使った簡単な例を示します。

class Employee 
{ 
    String name; 
    int salary; 

    Employee() 
    { 
     name = "Employee"; 
     salary = 5000; 
    } 
    public String getName() 
    { 
     return name; 
    } 
    public int getSalary() 
    { 
     return salary; 
    } 
} 
class Manager extends Employee 
{ 
    int bonus; 
    int salary; 

    Manager() 
    { 
     bonus = 1000; 
     salary = 6000; 
    } 
    public int getBonus() 
    { 
     return bonus; 
    } 
    public int getSalary() 
    { 
     return salary; 
    } 
} 

class Test 
{   
    public static void main(String[] args) 
    { 
     Employee e = new Employee(); 
     System.out.println(e.getName()); 
     //System.out.println(e.getBonus()); 
     System.out.println(e.getSalary()); 

     System.out.println(); 

     Manager m = new Manager(); 
     System.out.println(m.getName()); 
     System.out.println(m.getBonus()); 
     System.out.println(m.getSalary()); 

     System.out.println(); 

     Employee em = new Manager(); 
     System.out.println(em.getName());     
     //System.out.println(em.getBonus());    
     System.out.println(((Manager)em).getBonus()); 
     System.out.println(em.getSalary());  
     } 
} 

コンパイラは、操作を呼び出す前に参照型を探します。 Employeeにボーナスメソッドがないため、em.getBonus()は機能しません。 しかし、キャストを使って、それを動作させることができます。 ((マネージャー)EM。)getBonus()

理由コンパイラは次のようにそれは上の任意の操作を呼び出す前に、参照型を探し理由:

マネージャー[]マネージャー=新しいマネージャー[10]。

従業員の[]配列にこの配列を変換することが合法である:

社員[]スタッフ=マネージャ。 // OK

確かに、あなたは考えるかもしれません。結局、manager [i]がマネージャであれば、それも従業員です。しかし実際には、驚くべきことが起こっています。マネージャーとスタッフは同じアレイへの参照であることに注意してください。

今[0]新しい従業員( "ジョンEipe"、...)を=ステートメント

スタッフを検討します。

コンパイラはこの割り当てをうまく許可します。 しかし、staff [0]とmanager [0]は同じ参照であるため、単なる従業員を経営陣に密輸しているかのように見えます。 ランク。

これは非常に悪いことです。呼び出し側のマネージャー[0] .setBonus(1000)は 存在しないインスタンスフィールドにアクセスしようとし、隣接するメモリを破壊します。 このような破損が発生しないように、すべての配列は、作成された の要素タイプを覚えており、互換性のある参照のみが に格納されていることを監視します。たとえば、新しいManager [10]として作成された配列は、 マネージャの配列であることを記憶しています。従業員参照を格納しようとすると、ArrayStoreExceptionが発生します。

+1

非常に明確な例と説明。あなたが言うように、それは「初心者の間」です:Dあなたの例として、私はそれを理解しています:あなたが誰かを従業員と呼ぶと(実際はマネージャです)、コンパイラは従業員をマネージャとしてあなたは '型キャスト': "この従業員はマネージャーでなければなりません、右:D – hqt

3

ボックスのアナロジーが間違っているが、代わりにis aの関係を考えます。

最初の例ではLCD extends Monitor、つまりLCD is a Monitorです。したがって、Monitorが期待される場所であれば、LCDは問題ありません。あなたがコードを見るのではなく、現実の言葉で考えると、正しいことが分かります。あなたが一般的に(例えば写真を表示する)モニターが期待することができるすべてのものは、LCDモニターが行います。

第2の例では、LCDはモニタではないため、エラーメッセージが表示されます。

+2

私はDoyleに言うように私は分かりません:なぜ「LCD」に「Monitor」を割り当てることができますか? 'Monitor'はしないプロパティです。通常の生活では、 'LCD'が' Monitor'と言うことができます。しかし、私は想像することはできません、なぜ 'LCD'変数のような' Monitor'変数を使うことができますか? – hqt

+2

はい、これらのプロパティは関係ありません。誰かが一杯の水を頼んだら、ガラスがプラスチック、ガラス、金属製かどうか、ハンドルがあってもなくてもかまいませんが、実際にはマグカップならどんな種類の装飾があれば持っている。いいえ、唯一重要なのは、水を保持できることと、そこから水を摂ることができるということだけです。ここでも同じことが言えます:メソッドが 'Monitor'型を返すように定義することによって、それが持つ可能性がある追加のプロパティに単純に関心がないと宣言します。 – biziclop

+2

ああ。ありがとうございます。ですから、誰かが「私に水を与えてください」と尋ねると、あなたは意味します。そして、あなたは彼に金属ガラスまたはプラスチックガラスを与えることができます。 – hqt

5

2番目(エラー)のケースでは、LCDが実際にMonitorに拡張されていることを忘れてしまいました。 「通常の」スタンドアロンクラスを定義しているだけなので、new LCD()ではなく、のインスタンスはMonitorです。 (コメントするに応じて)

class LCD extends Monitor { 
    //some other method or function not in Monitor Class. Example: 
    boolean isSamsung; 
    public LCD whatkindLCD(){   
    }  
} 

編集:あなたはこのようなLCDクラスを宣言した場合

コンパイラが幸せでなければなりませんそれは全くLCDクラスは余分を持っているという問題ではありません特性/方法はMonitorと比較されます。 getMonitor()と呼ばれるコードは、Monitorのすべてのメソッドとプロパティと振る舞いを持つもの、つまりMonitorが返ってくるだけです。

したがって、MonitorクラスのturnOffdisplayBitmap(int[][] data)メソッドがある場合は、LCDクラスにもこれらのメソッドがあります。 LCDのインスタンスは、必要なときにMonitorとして振舞うことができます - これはOO言語のサブクラス化の基本原則です。だから何かがいつでもMonitorが欲しいときは、LCD、あるいはCRTまたはSamsungLCDのインスタンスを与えることができます。そうすれば、正しいメソッド/プロパティが存在し、呼び出すことができるとコンパイラが満足することができます。

(技術的にはこれが正式な定義のようなLiskov substitution principleあなたの場合ですが、細部のそのレベルでそれを理解する必要はありません。)

+2

はい。私はなぜ 'class LCD'が間違っているのか知っています。私が知らないのは、なぜ、 'LCD'に' Monitor'を割り当てることができるのかということです。なぜなら、 'LCD'には' Monitor'がないという性質があるからです。 – hqt

+3

ああ。あなたのリンクに感謝します。私はこの単純な思考が原則を背後に持っているとは想像できません。興味深い ! – hqt

0

「モニター」型を返すgetMonitorあなたの方法。

モニターを使用してクラスLCDを拡張すると、LCD モニターであることをコンパイラに伝えます。 を削除すると、LCDクラスはプレーンクラスになり、モニタータイプにはなりません。 あなたが

public LCD getMonitor(){ 
     // code here 
} 

にごgetMonitorを変更した場合、エラーが行きます。

関連する問題