簡體   English   中英

關於繼承Java類的性質的問題

[英]Question on the nature of inherited Java classes

所以我認為我有一個非常基本的問題。 假設您的項目com.bee.buzz中包含一個名為com.cow.moo的開源Java程序。

moo有很多很棒的課程,其中大部分是你不想觸摸的,但是有一些你做的。 現在,在這一點上,最好的辦法是擴展你想要修改的類,對吧? (我知道有很多關於擴展與實現的說法,但這些類都不是接口,所以這是不可能的。)

我的問題是,說這是moo中的類:

package com.cow.moo;
public class Milk {
    private float currentMilk;
    public int getMilk() { /* Stuff */ }
    public float convertToGallons (float liquid) { /* More Stuff */ }
}

現在,假設我想在擴展Milk的新類中使用getMilk。 但是,Milk中的getMilk依賴於私有變量(如currentMilk)和其他我不會包含的函數(如convertToGallons。)如果我希望我的新函數正常工作,我是否必須包含其他變量和函數? 我不想大量修改函數,只需添加一點就可以了。 最好的方法是什么?

一般來說,建立一個更大的項目的提示也是有用的。 我認為這里的一些Java專家甚至不會花五秒鍾來得出答案。 謝謝你的時間。

一般建議是贊成合成而不是繼承

比如說,你有一個接口和一個現有的實現,大多數符合你的需要,比如

public interface MilkProvider { public float getMilk(); }
public class Milk implements MilkProvider { // same as you example }

並需要另一個自定義實現,你可以這樣編碼:

public class MyMilk implements MilkProvider {
  private MilkProvider milk; 

  public MyMilk(int someValue) {
    milk = new Milk(someValue);  // unfortunatly we can't get rid of a depencency
                                 // to the concrete class because we need to create
                                 // something. An existing factory could help, but
                                 // but usually there's none implemented.
  }

  public float getMilk() {
    float result = milk.getMilk();
    // do somethink with the result
    return float;
  }
}

我認為在這種情況下,更好的解決方案將是多態(靜態多態),或者您可以使用反射( 不要使用這種方式 )來訪問私有變量。

現在,假設我想在擴展Milk的新類中使用getMilk。 但是,Milk中的getMilk依賴於私有變量(如currentMilk)和其他我不會包含的函數(如convertToGallons。)如果我希望我的新函數正常工作,我是否必須包含其他變量和函數?

您不必包含公共函數和變量。 繼承的核心概念是,作為子類,您可以免費獲得子類中包含的所有父類的公共(和受保護)成員。 所以你的子類(比如說HoneyMilk)可以從一開始就調用convertToGallons

在這種情況下重寫getMilk會非常棘手,因為它依賴於私有變量(您的子類無法訪問)。 我的建議是將你的思維方式從把班級視為“白盒子”轉變為“黑匣子”。 我的意思是你應該實現你的被覆蓋版本的getMilk ,就好像你實際上看不到Milk的源代碼一樣。 雖然它可能看起來像一個迂回的解決方案(我的意思是,為什么我不能在這里調整這一行?!),這將迫使你只使用父類公開公開的子類來實現你的子類。 它還強調抽象的重要性,這對於開發大型項目絕對至關重要。

如果它們是公共的,您可以通過方法訪問器(getter和setter)擴展類和訪問實例變量。

您可以使用AOP(面向方面​​編程)在運行時更改moo類,而無需更改其源。

請仔細閱讀一些“ 組合與繼承”主題

希望這會幫助你。

除非你使用丑陋的Java反射,否則你將無法使用私有類成員。 如果我是你(並且更改不是太重,在這種情況下我會分叉原始項目),我會考慮在運行時修改代碼或靜態使用方面編織(面向方面​​編程)。 AspectJ可能看起來好像有一個很好的學習曲線,但它是一個很好的工具,可以在你的工具箱中完美匹配你的需求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM