OOP Design Frage (ähnlich zu Circle-Ellipse Problematik...)



  • Hallo Leute.

    In einem kleinen 2D Pacman Game habe ich zwei Klasse namens Vector2df und Direction (sozusagen ein NormalenVektor)

    Hier ein kleiner Code-Ausschnitt:

    public class Vector2df {
    
        /** The x coordinate */
        private int x;
    
        /** The y coordinate */
        private int y;
    
        public Vector2df()
        {
            x = 0;
            y = 0;
        }
    
        public Vector2df( int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    
        public void set( Vector2df newPos )
        {
            this.x = newPos.x;
            this.y = newPos.y;
        }
    
        public void set( int x, int y )
        {
        	this.x = x;
    	this.y = y;
    
        // "operator overloading" methods:
    
        public Vector2df times( int a )
        {
        	return new Vector2df( this.x * a, this.y * a );
        }
    
        public Vector2df times( Vector2df v )
        {
        	return new Vector2df( this.x * v.x, this.y * v.y );
        }
    
        public Vector2df add( int a )
        {
        	return new Vector2df( this.x + a, this.y + a );
        }
    
        public Vector2df add( Vector2df v )
        {
        	return new Vector2df( this.x + v.x, this.y + v.y );
        }
    
        //etc...
    }
    

    Nun wollte ich eine Art RichtungsKlasse machen, die einfach ein Vekor mit der Normallänge 1 ist. Da ich auch die Methoden der Vector2df Klasse wiederverwenden wollte habe ich einfach von dieser geebert. Hier der Code:

    public class Direction extends Vector2df
    {
    	final public static int NONE = 4;
    	final public static int NORTH = 0;
    	final public static int EAST = 1;
    	final public static int SOUTH = 2;
    	final public static int WEST = 3;
    
    	private int name = NONE;
    
    	public static Direction create( int direction )
    	{
    		switch( direction )
    		{
    			case NORTH:
    				return new Direction( 0, -1, NORTH );
    			case EAST:
    				return new Direction( 1, 0, EAST );
    			case SOUTH:
    				return new Direction( 0, 1, SOUTH );
    			case WEST:
    				return new Direction( -1, 0, WEST );
    			default:
    				return new Direction( 0, 0, NONE );
    		}
    	}
    
    	private Direction( int x, int y, int value )
    	{
    		super( x, y );
    		name = value;
    	}
    }
    

    Das ganze klappte auch hervorragend und ich hatte keine Probleme mit dem Code.

    Erst im Nachhinein ist mir aber aufgefallen, das ich die Eigenschaften eines Direction-Objekts von aussen zerstören kann, etwa so:

    Direction dir = Direction.create( Direction.EAST );
    Vector2df vec = dir;
    
    // dir ist jetzt kein gültiges Direction Objekt mehr im Sinn, dass die Länge
    // immer nur eins sein darf und name mit der tatsächlichen Richtung übereinstimmt
    vec.set( 22, 22 );
    

    Als ich ein bisschen über dieses Problem nachgedacht habe, kam mir dann das "klassische" Kreis-Ellipse Problem in den Sinn. Ein Kreis ist ja auch eine Ellipse, aber nur solange ein Kreis falls die beiden (Ellipsen)-Radien gleich sind...

    Jetzt zu meiner Frage, gibts zu diesem Problem irgend eine elegante Lösung (falls ja welche, die "Experten" scheinen sich ja beim Kreis-Ellipse Problem auch nicht alle einig zu sein...) oder muss ich einfach von den Direction-Anwendern erwarten, dass sie nur das machen, was sie auch dürfen.

    Danke schon mal im Voraus.
    Edit: gerade ist mir eingefallen, dass ich in der Direction-Klasse ja einfach die Set-Methoden überschreiben könnte und eine Exception oder so werfen, falls der User einen ungültigen Wert übergibt... ich finde es zwar nicht eine sehr saubere Lösung, da ja der User erwartet dass er bei einem Vector2df durchaus die Koordinaten verändern darf...



  • ich wuerde direction nicht von vector erben lassen. stattdessen
    wuerde ich vector als member von direction nehmen und nur methoden
    anbieten um die richtung zu aendern.
    z.b. direction.east() ...


Anmelden zum Antworten