2016-08-17 125 views
10

我正在嘗試編寫2D遊戲引擎,並試圖實現一個視口系統,以便在特定視口中繪製遊戲座標時將轉換爲屏幕座標而不必手動進行轉換。2D二維遊戲引擎封裝器

我想要做的是創建一個Graphics2D包裝,增加一個setViewport方法。

我看到它的方式有2種選擇:

  1. 創建具有Graphics2D的一個實例,具有所有的相同方法Graphics2DsetViewport,只是一類呼籲Graphics2D各自的方法實例。

  2. 子類Graphics2D,只是增加一個setViewport方法,然後就從Graphics2D轉型爲這個新類

我嘗試#2#因爲1顯得很不切實際,但遇到了一個ClassCastException。我無法將GraphicsGraphics2D投射到這個新班級。在演員陣容之前(GraphicsGraphics2D)打印圖形對象時,都會以sun.java2d.SunGraphics2D的形式出現。

我在做一些根本錯誤的嘗試子類化和施放?如果不是,我該如何解決這個問題?

+0

我不認爲任何試圖繼承的Graphics2D是要的任何解決方案工作得很好。 –

+0

我沿着一個大學課程的幻燈片(並非實際上課),他們說「使用setViewport()方法爲Graphics2D創建包裝 - 繪製視口時,在您的Graphics2D包裝器中切換一個標記,每當繪製一個形狀時需要轉換遊戲 - >屏幕座標 - 在每個對象自己的onDraw()調用中分別進行遊戲對象變換 - 完成繪製視口時取消標記包裝「是否有其他一些包裝的解釋? –

+0

有趣 - 你有鏈接到這個幻燈片集合? –

回答

3

一個OO設計priciple是「在繼承青睞組成」,這使用包裝類裝飾設計模式(這是在我看來,什麼是包裝在使用過程中的意思是來達到的滑動)。所以,你做了什麼,其實是爲一些原因優雅解決方案:

  • 它能防止今後的實施改變Graphics2D,如果您使用繼承和不幸的新方法被添加到Graphics2D與與新方法相同的簽名和不同的返回類型,您的類將不再編譯。如果您使用相同的簽名和返回類型,則可以覆蓋Graphics2D中的新方法,該方法可能(並且)會導致幾天令人沮喪的調試。

  • 以這種方式繼承違反封裝使得軟件在長期運行中變得脆弱和容易出錯。

  • 使用你是保護從未來的變化你的類在類的與構成組成,你的類將向前所有的方法調用它的privateGraphics2D實例,並單獨處理轉化座標。

  • 它還考慮到將來很容易的擴展,使用繼承將使您與目前的Graphics2D實現相關聯,這會潛在地限制您的類的性能。

這樣的例子存在Java API中:該Properties類擴展HashTable,這說明使用不當繼承因爲Properties不是一個HashTable,它並不意味着以同樣的方式使用。在這種情況下,撥打Properties p.getProperty(key)可能會得到與p.get(key)不同的結果,因爲後一種情況不考慮默認值。

裝飾設計模式:

public class Wrapper { 
    private WrappedClass w; 

    public Wrapper(WrappedClass w) { 
     this.w = w; 
    } 

    // Forward calls to WrappedClass methods to the private instance. 
    public ReturnType example(Argument a) { return w.example(a); } 

    // Add your methods here: 
} 

雖然這似乎是一個繁瑣的做法很值得在上述原因,從長遠來看。 Java API中接口的存在,例如上面的HashSetSet接口,使得編寫這樣的類更容易,儘管我不知道Graphics2D是否存在這樣的接口。

來源:有效的Java第二版 - 約書亞布洛赫

+0

+1,並被接受用於提供這種設計決策背後的邏輯推理。在基本的Graphics2D之上添加更多的功能,這絕對是開放的。謝謝! –

+0

非常歡迎! –

2

我爲我寫的遊戲創建了一個座標系。隨意使用這些類作爲例子。

以下是CoordinateSystem類。

package com.ggl.game.utilities; 

import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.geom.Point2D; 

/** 
* <p> 
* This class creates a Cartesian and Polar coordinate system to overlay a Swing 
* drawing area (usually a <code>JPanel</code>). The user of the class sets a 
* limit as to how far the X axis or the Y axis extends in the negative and 
* positive direction from (0, 0). Point (0, 0) will be placed in the center of 
* the drawing area. 
* </p> 
* <p> 
* Since the drawing area is usually not square, the limit applies to the 
* shorter dimension. The actual limits can be retrieved from this class, and 
* will change if the user of the application changes the drawing area size by 
* maximizing or normalizing the application <code>JFrame</code> window. 
* </p> 
* <p> 
* Using a Cartesian or Polar coordinate system frees the user of this class 
* from having to worry about Swing pixel coordinates. 
* </p> 
* 
* @author Gilbert G. Le Blanc 
* @version 1.0 - 23 February 2015 
* 
* @see com.ggl.game.utilities.Polar2D 
* @see java.awt.geom.Point2D 
* @see javax.swing.JFrame 
* @see javax.swing.JPanel 
*/ 
public class CoordinateSystem { 

    private double conversionFactor; 
    private double xLimit; 
    private double yLimit; 

    private int height; 
    private int width; 

    /** 
    * <p> 
    * This creates a Cartesian and Polar coordinate system over a Swing drawing 
    * area (usually a <code>JPanel</code>). If the drawing area is square, the 
    * X axis extends from -limit to limit and the Y axis extends from -limit to 
    * limit. 
    * </p> 
    * <p> 
    * If the drawing area is not square, then the smaller dimension, either X 
    * or Y, extends from -limit to limit. The larger dimension extends beyond 
    * the limit in both directions. 
    * </p> 
    * <p> 
    * Since most displays are not square, the X and Y axis will usually have 
    * different limits. 
    * </p> 
    * 
    * @param limit 
    *   - The limit of the X and Y axis in a Cartesian coordinate 
    *   system. 
    * @param width 
    *   - The width of the drawing area in pixels. 
    * @param height 
    *   - The height of the drawing area in pixels. 
    */ 
    public CoordinateSystem(double limit, int width, int height) { 
     this.width = width; 
     this.height = height; 

     if (width > height) { 
      this.xLimit = limit * width/height; 
      this.yLimit = limit; 
      this.conversionFactor = (limit + limit)/(double) height; 
     } else if (width < height) { 
      this.xLimit = limit; 
      this.yLimit = limit * height/width; 
      this.conversionFactor = (limit + limit)/(double) width; 
     } else { 
      this.xLimit = limit; 
      this.yLimit = limit; 
      this.conversionFactor = (limit + limit)/(double) width; 
     } 
    } 

    /** 
    * This method changes the drawing area dimension, along with the X and Y 
    * axis limits. 
    * 
    * @param dimension 
    *   - A <code>Dimension</code> with the new drawing area 
    *   dimension. 
    */ 
    public void setDrawingSize(Dimension dimension) { 
     setDrawingSize(dimension.width, dimension.height); 
    } 

    /** 
    * This method changes the drawing area width and height, along with the X 
    * and Y axis limits. 
    * 
    * @param width 
    *   - The width of the drawing area in pixels. 
    * @param height 
    *   - The height of the drawing area in pixels. 
    */ 
    public void setDrawingSize(int width, int height) { 
     xLimit = xLimit/this.width * width; 
     yLimit = yLimit/this.height * height; 

     this.width = width; 
     this.height = height; 
    } 

    /** 
    * This method returns the Cartesian coordinate limit for the X axis. 
    * 
    * @return The Cartesian coordinate limit for the X axis. 
    */ 
    public double getxLimit() { 
     return xLimit; 
    } 

    /** 
    * This method returns the Cartesian coordinate limit for the Y axis. 
    * 
    * @return The Cartesian coordinate limit for the Y axis. 
    */ 
    public double getyLimit() { 
     return yLimit; 
    } 

    /** 
    * This method converts a Polar coordinate distance and theta angle in 
    * radians to a pixel location on a drawing area. 
    * 
    * @param distance 
    *   - A Polar coordinate distance 
    * @param theta 
    *   - A Polar coordinate theta angle in radians 
    * @return A pixel location on a drawing area. 
    */ 
    public Point convertPolarToPixels(double distance, double theta) { 
     return convertToPixels(new Polar2D.Double(distance, theta)); 
    } 

    /** 
    * This method converts a Cartesian coordinate x and y to a pixel location 
    * on a drawing area. 
    * 
    * @param x 
    *   - A Cartesian coordinate x. 
    * @param y 
    *   - A Cartesian coordinate y. 
    * @return A pixel location on a drawing area. 
    */ 
    public Point convertPointToPixels(double x, double y) { 
     return convertToPixels(new Point2D.Double(x, y)); 
    } 

    /** 
    * This method converts a Polar coordinate to a pixel location on a drawing 
    * area. 
    * 
    * @param polar 
    *   - A Polar coordinate. 
    * @return A pixel location on a drawing area. 
    */ 
    public Point convertToPixels(Polar2D polar) { 
     double x = polar.getDistance() * Math.cos(polar.getTheta()); 
     double y = polar.getDistance() * Math.sin(polar.getTheta()); 
     return convertToPixels(new Point2D.Double(x, y)); 
    } 

    /** 
    * This method converts a Cartesian coordinate to a pixel location on a 
    * drawing area. 
    * 
    * @param cartesian 
    *   - A Cartesian coordinate. 
    * @return A pixel location on a drawing area. 
    */ 
    public Point convertToPixels(Point2D cartesian) { 
     int x = (int) Math 
       .round((cartesian.getX() + xLimit)/conversionFactor); 
     int y = (int) Math.round((-cartesian.getY() + yLimit) 
       /conversionFactor); 
     return new Point(x, y); 
    } 

    /** 
    * This method converts a pixel location on a drawing area to a Cartesian 
    * coordinate. 
    * 
    * @param x 
    *   - The x pixel location. 
    * @param y 
    *   - The y pixel location. 
    * @return A Cartesian coordinate. 
    */ 
    public Point2D convertToCartesian(int x, int y) { 
     return convertToCartesian(new Point(x, y)); 
    } 

    /** 
    * This method converts a pixel location on a drawing area to a Cartesian 
    * coordinate. 
    * 
    * @param point 
    *   - The pixel location. 
    * @return A Cartesian coordinate. 
    */ 
    public Point2D convertToCartesian(Point point) { 
     double x = (double) point.x * conversionFactor - xLimit; 
     double y = (double) -point.y * conversionFactor + yLimit; 
     return new Point2D.Double(x, y); 
    } 

    /** 
    * This method converts a pixel location on a drawing area to a Polar 
    * coordinate. 
    * 
    * @param x 
    *   - The x pixel location. 
    * @param y 
    *   - The y pixel location. 
    * @return A Polar coordinate. 
    */ 
    public Polar2D convertToPolar(int x, int y) { 
     return convertToPolar(new Point(x, y)); 
    } 

    /** 
    * This method converts a pixel location on a drawing area to a Polar 
    * coordinate. 
    * 
    * @param point 
    *   - The pixel location. 
    * @return A Polar coordinate. 
    */ 
    public Polar2D convertToPolar(Point point) { 
     double x = (double) point.x * conversionFactor - xLimit; 
     double y = (double) -point.y * conversionFactor + yLimit; 
     double distance = Math.sqrt(x * x + y * y); 
     double theta = Math.atan2(y, x); 
     return new Polar2D.Double(distance, theta); 
    } 

} 

這裏是Polar2D類。它是Point2D類的克隆。

package com.ggl.game.utilities; 

/** 
* The <code>Polar2D</code> class defines a point representing a location in 
* distance, theta angle coordinate space. 
* <p> 
* This class is only the abstract superclass for all objects that store a 2D 
* coordinate. The actual storage representation of the coordinates is left to 
* the subclass. 
* 
* @version 1.0 - 23 February 2015 
* @author Jim Graham (author of Point2D), Gilbert Le Blanc 
*/ 
public abstract class Polar2D implements Cloneable { 
    /** 
    * The <code>Float</code> class defines a point specified in float 
    * precision. 
    */ 
    public static class Float extends Polar2D { 
     /** 
     * The distance of this <code>Polar2D</code>. 
     * 
     * @since 1.7 
     */ 
     public float distance; 
     /** 
     * The theta angle of this <code>Polar2D</code>. 
     * 
     * @since 1.7 
     */ 
     public float theta; 

     /** 
     * Constructs and initializes a <code>Polar2D</code> with coordinates 
     * (0,&nbsp;0). 
     * 
     * @since 1.7 
     */ 
     public Float() { 
     } 

     /** 
     * Constructs and initializes a <code>Polar2D</code> with the specified 
     * coordinates. 
     * 
     * @param distance 
     *   The distance to which to set the newly constructed 
     *   <code>Polar2D</code> 
     * @param theta 
     *   The theta angle in radians to which to set the newly 
     *   constructed <code>Polar2D</code> 
     * @since 1.7 
     */ 
     public Float(float distance, float theta) { 
      this.distance = distance; 
      this.theta = theta; 
     } 

     /** 
     * Returns the distance of this <code>Polar2D</code> in 
     * <code>double</code> precision. 
     * 
     * @return the distance of this <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public double getDistance() { 
      return (double) distance; 
     } 

     /** 
     * Returns the theta angle in radians of this <code>Polar2D</code> in 
     * <code>double</code> precision. 
     * 
     * @return the theta angle in radians of this <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public double getTheta() { 
      return (double) theta; 
     } 

     /** 
     * Returns the theta angle in degrees of this <code>Polar2D</code> in 
     * <code>double</code> precision. 
     * 
     * @return the theta angle in degrees of this <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public double getThetaInDegrees() { 
      double degrees = 180D/Math.PI * theta; 
      return (degrees < 0D) ? degrees + 360D : degrees; 
     } 

     /** 
     * Sets the location of this <code>Polar2D</code> to the specified 
     * <code>double</code> distance and theta angle in radians. 
     * 
     * @param distance 
     *   The distance to which to set this <code>Polar2D</code> 
     * @param theta 
     *   The theta angle in radians to which to set this 
     *   <code>Polar2D</code> 
     * @since 1.7 
     */ 
     @Override 
     public void setLocation(double distance, double theta) { 
      this.distance = (float) distance; 
      this.theta = (float) theta; 
     } 

     /** 
     * Sets the location of this <code>Polar2D</code> to the specified 
     * <code>float</code> coordinates. 
     * 
     * @param distance 
     *   The distance to which to set this <code>Polar2D</code> 
     * @param theta 
     *   The theta angle in radians to which to set this 
     *   <code>Polar2D</code> 
     * @since 1.7 
     */ 
     public void setLocation(float distance, float theta) { 
      this.distance = distance; 
      this.theta = theta; 
     } 

     /** 
     * Returns a <code>String</code> that represents the value of this 
     * <code>Polar2D</code>. 
     * 
     * @return A <code>String</code> representation of this 
     *   <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public String toString() { 
      return "Polar2D.Float[" + distance + ", " + theta + "]"; 
     } 
    } 

    /** 
    * The <code>Double</code> class defines a point specified in 
    * <code>double</code> precision. 
    */ 
    public static class Double extends Polar2D { 
     /** 
     * The distance of this <code>Polar2D</code>. 
     * 
     * @since 1.7 
     */ 
     public double distance; 
     /** 
     * The theta angle in radians of this <code>Polar2D</code>. 
     * 
     * @since 1.7 
     */ 
     public double theta; 

     /** 
     * Constructs and initializes a <code>Polar2D</code> with (0,&nbsp;0) 
     * distance and theta angle in radians. 
     * 
     * @since 1.7 
     */ 
     public Double() { 
     } 

     /** 
     * Constructs and initializes a <code>Polar2D</code> with the specified 
     * coordinates. 
     * 
     * @param distance 
     *   The distance to which to set the newly constructed 
     *   <code>Polar2D</code> 
     * @param theta 
     *   The theta angle in radians to which to set the newly 
     *   constructed <code>Polar2D</code> 
     * @since 1.7 
     */ 
     public Double(double distance, double theta) { 
      this.distance = distance; 
      this.theta = theta; 
     } 

     /** 
     * Returns the distance of this <code>Polar2D</code> in 
     * <code>double</code> precision. 
     * 
     * @return The distance of this <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public double getDistance() { 
      return distance; 
     } 

     /** 
     * Returns the theta angle in radians of this <code>Polar2D</code> in 
     * <code>double</code> precision. 
     * 
     * @return The theta angle in radians of this <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public double getTheta() { 
      return theta; 
     } 

     /** 
     * Returns the theta angle in degrees of this <code>Polar2D</code> in 
     * <code>double</code> precision. 
     * 
     * @return The theta angle in degrees of this <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public double getThetaInDegrees() { 
      double degrees = 180D/Math.PI * theta; 
      return (degrees < 0D) ? degrees + 360D : degrees; 
     } 

     /** 
     * Sets the location of this <code>Polar2D</code> to the specified 
     * <code>double</code> coordinates. 
     * 
     * @param distance 
     *   The distance to which to set this <code>Polar2D</code> 
     * @param theta 
     *   The theta angle in radians to which to set this 
     *   <code>Polar2D</code> 
     * @since 1.7 
     */ 
     @Override 
     public void setLocation(double distance, double theta) { 
      this.distance = distance; 
      this.theta = theta; 
     } 

     /** 
     * Returns a <code>String</code> that represents the value of this 
     * <code>Polar2D</code>. 
     * 
     * @return A <code>String</code> representation of this 
     *   <code>Polar2D</code>. 
     * @since 1.7 
     */ 
     @Override 
     public String toString() { 
      return "Polar2D.Double[" + distance + ", " + theta + "]"; 
     } 
    } 

    /** 
    * This is an abstract class that cannot be instantiated directly. 
    * Type-specific implementation subclasses are available for instantiation 
    * and provide a number of formats for storing the information necessary to 
    * satisfy the various accessor methods below. 
    * 
    * @see java.awt.geom.Polar2D.Float 
    * @see java.awt.geom.Polar2D.Double 
    * @see java.awt.Point 
    */ 
    protected Polar2D() { 
    } 

    /** 
    * Returns the distance of this <code>Polar2D</code> in <code>double</code> 
    * precision. 
    * 
    * @return The distance of this <code>Polar2D</code>. 
    * @since 1.7 
    */ 
    public abstract double getDistance(); 

    /** 
    * Returns the theta angle in radians of this <code>Polar2D</code> in 
    * <code>double</code> precision. 
    * 
    * @return The theta angle in radians of this <code>Polar2D</code>. 
    * @since 1.7 
    */ 
    public abstract double getTheta(); 

    /** 
    * Returns the theta angle in degrees of this <code>Polar2D</code> in 
    * <code>double</code> precision. 
    * 
    * @return The theta angle in degrees of this <code>Polar2D</code>. 
    * @since 1.7 
    */ 
    public abstract double getThetaInDegrees(); 

    /** 
    * Sets the location of this <code>Polar2D</code> to the specified 
    * <code>double</code> coordinates. 
    * 
    * @param distance 
    *   The distance of this <code>Polar2D</code> 
    * @param theta 
    *   The theta angle in radians of this <code>Polar2D</code> 
    * @since 1.7 
    */ 
    public abstract void setLocation(double distance, double theta); 

    /** 
    * Sets the location of this <code>Polar2D</code> to the same coordinates as 
    * the specified <code>Polar2D</code> object. 
    * 
    * @param p 
    *   the specified <code>Polar2D</code> the which to set this 
    *   <code>Polar2D</code> 
    * @since 1.7 
    */ 
    public void setLocation(Polar2D p) { 
     setLocation(p.getDistance(), p.getTheta()); 
    } 

    /** 
    * Returns the square of the distance between two points. 
    * 
    * @param distance1 
    *   The distance of the first point 
    * @Parm theta1 The theta angle in radians of the first point 
    * @param distance2 
    *   The distance of the second point 
    * @param theta2 
    *   The theta angle in radians of the second point 
    * @return The square of the distance between the two specified points. 
    */ 
    public static double distanceSq(double distance1, double theta1, 
      double distance2, double theta2) { 
     double x1 = distance1 * Math.cos(theta1); 
     double y1 = distance1 * Math.sin(theta1); 
     double x2 = distance2 * Math.cos(theta2); 
     double y2 = distance2 * Math.sin(theta2); 
     return (x1 * x2 + y1 * y2); 
    } 

    /** 
    * Returns the distance between two points. 
    * 
    * @param distance1 
    *   The distance of the first point 
    * @param theta1 
    *   The theta angle in radians of the first point 
    * @param distance2 
    *   The distance of the second point 
    * @param theta2 
    *   The theta angle in radians of the second point 
    * @return The distance between the two specified points. 
    */ 
    public static double distance(double distance1, double theta1, 
      double distance2, double theta2) { 
     double x1 = distance1 * Math.cos(theta1); 
     double y1 = distance1 * Math.sin(theta1); 
     double x2 = distance2 * Math.cos(theta2); 
     double y2 = distance2 * Math.sin(theta2); 
     return Math.sqrt(x1 * x2 + y1 * y2); 
    } 

    /** 
    * Returns the square of the distance from this <code>Polar2D</code> to a 
    * specified point. 
    * 
    * @param distance 
    *   The distance of the specified point 
    * @param theta 
    *   The theta angle in radians of the specified point 
    * @return The square of the distance between this <code>Polar2D</code> and 
    *   the specified point. 
    */ 
    public double distanceSq(double distance, double theta) { 
     double x1 = distance * Math.cos(theta); 
     double y1 = distance * Math.sin(theta); 
     double x2 = getDistance() * Math.cos(getTheta()); 
     double y2 = getDistance() * Math.sin(getTheta()); 
     return (x1 * x2 + y1 * y2); 
    } 

    /** 
    * Returns the square of the distance from this <code>Polar2D</code> to a 
    * specified <code>Polar2D</code>. 
    * 
    * @param pt 
    *   The specified <code>Polar2D</code> 
    * @return The square of the distance between this <code>Polar2D</code> to a 
    *   specified <code>Polar2D</code>. 
    */ 
    public double distanceSq(Polar2D pt) { 
     double x1 = pt.getDistance() * Math.cos(pt.getTheta()); 
     double y1 = pt.getDistance() * Math.sin(pt.getTheta()); 
     double x2 = getDistance() * Math.cos(getTheta()); 
     double y2 = getDistance() * Math.sin(getTheta()); 
     return (x1 * x2 + y1 * y2); 
    } 

    /** 
    * Returns the distance from this <code>Polar2D</code> to a specified point. 
    * 
    * @param distance 
    *   The distance of the specified point 
    * @param theta 
    *   The theta angle in radians of the specified point 
    * @return The distance between this <code>Polar2D</code> and a specified 
    *   point. 
    */ 
    public double distance(double distance, double theta) { 
     double x1 = distance * Math.cos(theta); 
     double y1 = distance * Math.sin(theta); 
     double x2 = getDistance() * Math.cos(getTheta()); 
     double y2 = getDistance() * Math.sin(getTheta()); 
     return Math.sqrt(x1 * x2 + y1 * y2); 
    } 

    /** 
    * Returns the distance from this <code>Polar2D</code> to a specified 
    * <code>Polar2D</code>. 
    * 
    * @param pt 
    *   the specified <code>Polar2D</code> 
    * @return The distance between this <code>Polar2D</code> and the specified 
    *   <code>Polar2D</code>. 
    */ 
    public double distance(Polar2D pt) { 
     double x1 = pt.getDistance() * Math.cos(pt.getTheta()); 
     double y1 = pt.getDistance() * Math.sin(pt.getTheta()); 
     double x2 = getDistance() * Math.cos(getTheta()); 
     double y2 = getDistance() * Math.sin(getTheta()); 
     return Math.sqrt(x1 * x2 + y1 * y2); 
    } 

    /** 
    * Creates a new object of the same class and with the same contents as this 
    * object. 
    * 
    * @return a clone of this instance. 
    * @exception OutOfMemoryError 
    *    if there is not enough memory. 
    * @see java.lang.Cloneable 
    * @since 1.7 
    */ 
    @Override 
    public Object clone() { 
     try { 
      return super.clone(); 
     } catch (CloneNotSupportedException e) { 
      // this shouldn't happen, since we are Cloneable 
      throw new InternalError(); 
     } 
    } 

    /** 
    * Returns the hash code for this <code>Polar2D</code>. 
    * 
    * @return a hash code for this <code>Polar2D</code>. 
    */ 
    @Override 
    public int hashCode() { 
     long bits = java.lang.Double.doubleToLongBits(getDistance()); 
     bits ^= java.lang.Double.doubleToLongBits(getTheta()) * 31; 
     return (((int) bits)^((int) (bits >> 32))); 
    } 

    /** 
    * Determines whether or not two points are equal. Two instances of 
    * <code>Polar2D</code> are equal if the values of their <code>x</code> and 
    * <code>y</code> member fields, representing their position in the 
    * coordinate space, are the same. 
    * 
    * @param obj 
    *   an object to be compared with this <code>Polar2D</code> 
    * @return <code>true</code> if the object to be compared is an instance of 
    *   <code>Polar2D</code> and has the same values; <code>false</code> 
    *   otherwise. 
    * @since 1.7 
    */ 
    @Override 
    public boolean equals(Object obj) { 
     if (obj instanceof Polar2D) { 
      Polar2D p2d = (Polar2D) obj; 
      return (getDistance() == p2d.getDistance()) 
        && (getTheta() == p2d.getTheta()); 
     } 
     return super.equals(obj); 
    } 
} 
+1

吉爾伯特,感謝您的回覆,並感謝您的努力和興趣。對於賞金,雖然我正在尋找一個規範的答案,展示瞭如何爲Graphics2D創建包裝類並使用它,如OP的鏈接中所述。 –

1

一種選擇是使用代理服務器。它可以讓你包裝所有的Graphics2D功能,而無需編寫每種方法。

的GraphicsView接口聲明的附加功能:

import java.awt.Rectangle; 

public interface GraphicsView { 
    void setViewport(Rectangle r); 
    Rectangle getViewport(); 
    boolean isViewportActive(); 
    void setViewportActive(boolean active); 
} 

的Graphics2DWrapperFactory代理到的Graphics2D + GraphicsView:

import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 

public class Graphics2DWrapperFactory { 
    public static Graphics2D wrapGraphics2D(final Graphics2D g) { 
     GraphicsView gv = new GraphicsView() { 
      // Implement new functionality here... 
      private boolean active; 
      Rectangle r; 
      @Override 
      public Rectangle getViewport() { 
       System.err.println("getViewport called"); 
       return r; 
      } 
      @Override 
      public void setViewport(Rectangle r) { 
       this.r = r; 
       System.err.println("setViewport called"); 
      } 
      @Override 
      public boolean isViewportActive() { 
       System.err.println("isViewportActive called"); 
       return active; 
      } 
      @Override 
      public void setViewportActive(boolean active) { 
       this.active = active; 
       System.err.println("setViewportActive called"); 
      } 
     }; 
     InvocationHandler invocationHandler = new GraphicsWrapperInvocationHandler(g, gv); 
     Class<?> interfaces[] = { Graphics2D.class, GraphicsView.class}; 
     return (Graphics2D) Proxy.newProxyInstance(g.getClass().getClassLoader(), interfaces, invocationHandler); 
    } 
    private static class GraphicsWrapperInvocationHandler implements InvocationHandler { 
     private final GraphicsView gv; 
     private final Graphics2D g2d; 
     public GraphicsWrapperInvocationHandler(Graphics2D g, GraphicsView gv) { 
      this.g2d = g; 
      this.gv = gv; 
     } 
     @Override 
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
      String methodName = method.getName(); 
      switch(methodName) { 
       // If the is calling one of the GraphicsView methods, delegate to gv 
       case "setViewport": 
       case "getViewport": 
       case "isViewportActive": 
       case "setViewportActive": 
        return method.invoke(gv, args); 
       // Otherwise, it's a Graphics2D methods. Delegate to g2d 
       default: 
        return method.invoke(g2d, args); 
      } 
     } 
    } 
}