2012-03-12 66 views
1

這裏是我想要使用一個簡化圖像加載過程的構造函數的問題。你需要做的只是一個文件路徑。如何使用構造函數將對象設置爲現有對象?

有可能通過繼承來做到這一點,或者我是否需要創建一個新的緩衝圖像對象? 這裏是代碼的理念,使其更容易理解。

public class specialImage extends BufferedImage { 

    specialImage(String path) { 
    super(); 
    this = ImageIO.read(new File(Path)); // <--- how can i Do this in java. 
    } 
} 

OR我應執行以下操作

class specialImage{ 

    BufferedImage manipulator; 

    specialImage (String path) { 
     manpiulator = ImageIO.read(new File(path)); 
    } 
    } 

------------------------ EDIT 1: ------------------------- 我試圖避免返回。我想創建一系列可以操作specialImage類的函數。像

specialImage objectName = new specialImage(FILE_PATH); 
objectName.toGrayscale(); 
objectName.specialTransformation(); 
//While still using the BufferedImage class, i.e., 
objectName.getRaster(); 

回答

1

對您的問題和具體的問題有一個普遍的答案。務實地,我們應該首先覆蓋特定的一個。

你應該按照這一點做點什麼。

public class SpecialImage { 

    // The thing isn't a manipulator, it's a BufferedImage 
    // I would suggest renaming this for ease of maintenance 
    BufferedImage manipulator; 

    public SpecialImage(String path) { 
    manpiulator = ImageIO.read(new File(path)); 
    } 

} 

除非您知道您的子類將與父類共享相同的「行爲」,否則請避免子類。通過將BufferedImage作爲一個字段加入您的課程,您使用的是一種稱爲「構圖」的技術,一般而言,如果有疑問,請使用favor composition over inheritance

當類別遵循Liskov Substitution Principle或近似英語術語時,當它們具有相同的「行爲」但修改了該「行爲」的實現時,繼承效果最佳。例如,BufferedImage s和VolatileImage s的行爲與java.awt.Image完全相同,但其中一個可以使用可訪問的緩衝區,另一個不能保證緩衝區可訪問性(或甚至緩衝區存在)。

您的問題的更一般的答案如下。

Object s被建模爲「事物」的實例,其中「事物」使用名爲Class的模板建模。構造是從模板或面向對象的術語中創建一個新的「事物」的過程,從它的Class中創建一個Object。根據這種理解,你可以看到,對現有的「事物」構建一個「事物」至多是尷尬的英語,而最壞的情況是近乎無意義的陳述。你可能意思是其中一個

  • 我該如何構建一個「東西」的副本?

如果你想要一個對象的第二個副本,您需要提供一個「拷貝構造函數」,這是返回的第一個「東西」第二,等價,拷貝構造函數的總稱。

public class Car { 

    private int speed; 

    public Car(int mph) { 
    // this is an optional keyword. I included it for clarity. 
    this.speed = mph; 
    } 

    // This is the copy constructor 
    public Car(Car other) { 
    this.speed = other.speed; 
    } 

    public int getSpeed() { 
    return speed; 
    } 

} 
  • 我怎樣才能使第二參考,以現有的「東西」?

您創建一個新名稱,並將其分配給一箇舊名稱。舊名稱(將在封底)產生一個參考,它將成爲新名稱的新值。引用大多是隱藏的,因爲對名稱的所有操作都會自動「取消引用」。

Car myCar = new Car(); 
Car yourCar = myCar; // assuming it is a shared car. 

爲了讓代碼的兩個部分引用相同的「東西」,你不需要使用構造函數,因爲它會創建兩件事情。而是使用兩個不同的「名稱」或「引用」。 Java中的引用有點像其他語言中的指針,只是它們受到許多有趣的限制。

  1. 它們不涉及真實的存儲位置。這允許垃圾收集來壓縮內存,而無需重寫未知數量的引用。內存壓縮包括將對象的數據存儲從一個起始地址移動到另一個起始地址,並且通過使用「內存引用標識」而不是實際地址,需要更改的唯一物理地址是「內存引用標識「到」物理地址「表(該表不能從用戶編寫的程序到達)。

  2. 它們不能指定任意位置。已命名的引用具有已聲明的類型,並且要分配的對象具有已聲明的類型。編譯器和運行時環境的強類型檢查保證只有兼容類型可以分配給一個命名參考。因此,不可能強制任意對象被不兼容的命名引用引用。

  3. 數學運算是被禁止的,或者更恰當的說,數學運算沒有被執行。這最後一個約束可以防止偏移一個已命名的引用,以便它可能引用具有可能不同的不兼容類型的不同對象。

記住這些項目,您的原始計劃將很好地工作;真正的問題是你將如何實現這些目標。如果您的「GrayScale」圖像是您的非GrayScale圖像的相同的東西,那麼使用相同的類(使用toGrayScale()方法)是一個很好的設計選擇。如果您的「GrayScale」圖像是不同的東西比您的非GrayScale圖像,然後有toGrayScale()返回第二個圖像是一個很好的設計選擇。

當你不做這些設計選擇時,面向對象的編程開始崩潰。您將對象看作「內存條」,避免創建新對象並丟棄舊對象,而不願意維護特定的「內存條」。除非您正在對內存條進行建模,否則這不是面向對象的設計,因此,您將在解決方案的每一步中與您的面向對象環境戰鬥,從而爲您提供所需的輸出。

祝你好運與你的努力。

+0

「_他們沒有提到真實的內存位置,這允許垃圾收集來壓縮內存,而不需要重寫未知數量的引用。」 - 這種情況幾十年來一直沒有發生。在32位上,引用是指針。在64位上,除非使用壓縮的OOPS,否則它們是指針。無論如何,GC確實需要在對象移動時重寫所有引用。 – Doradus 2016-07-20 02:16:38

0

這是使用靜態工廠可能是你需要的地方。

public enum SpecialImage {; // Utility class. 
    public static BufferedImage load(String path) { 
     return ImageIO.read(new File(Path)); // <--- how can i Do this in java. 
    } 
} 

一個使用靜態工廠像ImageIO.read(的缺點是它們不能是子類。

0

雖然您仍然可以從BufferedImage繼承,但仍然可以使用第二種方法,但是您必須將委託方法添加到您要在specialImage類中使用的所有BufferedImage方法中。

0
class ImageUtil { 
public static BufferedImage loadImage(final String path) { 
    BufferedImage image = ImageIO.read(new File(path)); 
    return image; 
} 
} 
0

你的第一個代碼嘗試說「工廠法」,所以這將工作:

public class SpecialImage extends BufferedImage { 
    SpecialImage(String path) { 
     super(); 
    } 

    public static SpecialImage create(String path) { 
     return ImageIO.read(new File(path)); 
    } 
} 

第二個代碼嘗試說「成分」,所以不知道你想做什麼,我不能評論,但似乎確定。

+0

好像你犯了一個錯誤。 ImageIO.read不返回SpecialImage。 – 2012-03-13 19:47:54

相關問題