Results 1 to 12 of 12
  1. #1
    MadJack is offline Member
    Join Date
    Sep 2010
    Location
    Qc
    Posts
    31
    Rep Power
    0

    Question Field definition for extending classes Question.

    I'm not entirely sure how to describe my problem clearly, so please bear with me.

    I've got a Galaxy Class.

    Then I have 3 classes that extend Galaxy: Spiral, Elliptical and Barred.

    Galaxy Class holds generic info like overall size, etc.

    Each particular galaxy type generates the galaxy itself plus some more fields and methods that are only used in that type of galaxy.

    Now, in my main class where everything goes, I have to define a variable that will hold the newly generated galaxy. Since everything is generated randomly, if I reference the new galaxy as Galaxy, it doesn't have the specific galaxy type's methods and fields.

    Example:
    Java Code:
    protected Galaxy galaxy;
    And later if I try to use:
    Java Code:
    galaxy.gSpheres
    it won't work because that's only in Elliptical galaxy.

    So, I guess the question becomes: Do I make a variable for each type and only use the right one when it has been made clear which type of galaxy will be generated? If so I'll have to "if" or "switch" everything pertaining to galaxy argument passing, so I can use the right type of galaxy...

    There's got to be an easier way.

    Please help. :)

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Often if you have a collection of parent type or a variable of parent type, you call parent type methods on it only. What specialized methods will you be calling on your Galaxy object that will be present in one subtype and not another?

  3. #3
    MadJack is offline Member
    Join Date
    Sep 2010
    Location
    Qc
    Posts
    31
    Rep Power
    0

    Default

    Quote Originally Posted by Fubarable View Post
    Often if you have a collection of parent type or a variable of parent type, you call parent type methods on it only. What specialized methods will you be calling on your Galaxy object that will be present in one subtype and not another?
    Here's are some snippets.

    Galaxy Class bits.

    I haven't put everything in here since there is superfluous methods that would only make it hard to see for the case here.
    Java Code:
    public class Galaxy {
    
        Global global;
        private int gWidthUnits;
        private int gHeightUnits;
        private int gDepthUnits;
        // Both the following are NOT x/y/z but x/z/y because of the plane the
        // galaxy is made on. Thickness in on the Y axis.
        protected int[] gMinSize = new int[3];
        protected int[] gMaxSize = new int[3];
        protected int galaxyType;
    
        public Galaxy () {}
    }
    Here's the complete Elliptical Class definition.
    Java Code:
    package galaxy;
    
    import Global.Global;
    import com.jme3.math.FastMath;
    import com.jme3.math.Vector3f;
    import java.util.ArrayList;
    
    /**
     *
     * @author MadJack
     */
    public class Elliptical extends Galaxy {
        private int starsBySphere = 0;
        private int numSpheres = 0;
    
        public void Elliptical() {
        }
    
        /***************************************************************************
         *	create_elliptical_galaxy
         *  @param g
         *      Global g contains all the information about the game.
         * @param stars
         *      stars is the ArrayList<Star> where we store our stars.
         *
         **************************************************************************/
        public Elliptical (Global g, ArrayList<Star> stars) {
    
            int maxX = 0;
            int maxY = 0;
            int maxZ = 0;
            int minX = 0;
            int minY = 0;
            int minZ = 0;
    
            // galaxy radius
            float galRadius = g.getRadius();
            // number of spheres used to draw stars around
            this.numSpheres = (int) galRadius / FastMath.nextRandomInt(5, 15);
            // number of stars by spheres
            this.starsBySphere = (int) (g.getNumStars() / numSpheres);
    
            float lonStars = starsBySphere / 180; //FastMath.PI
            float latStars = 180; //(FastMath.PI*2)
    
            float vDeg = (float) FastMath.PI / lonStars;
            float hDeg = (float) 2*FastMath.PI / latStars;
    
            for(int i = 1; i<numSpheres+1; i++) {
                galRadius -= galRadius/numSpheres*i;
                Vector3f vecXYZ = new Vector3f();
    
                // Coming up with latitude's value
                for (float lat = hDeg ; lat <= 2*FastMath.PI  ; lat+= hDeg) {
                    // longitude's value
                    for (float lon = hDeg ; lon <= FastMath.PI ; lon+= vDeg) {
                        if (stars.size() > starsBySphere*numSpheres ) {
                            System.out.println("Error, too many stars! "+stars.size());
                            lon = 564564564546f; lat = 564864654684f ; i = numSpheres+1;
                        } else {
                            vecXYZ.x = (galRadius/numSpheres*i) * FastMath.cos(lon) * FastMath.cos(lat) * jitter(galRadius/numSpheres*i);
                            vecXYZ.y = (galRadius/numSpheres*i) * FastMath.sin(lon) * FastMath.cos(lat) * jitter(galRadius/numSpheres*i);
                            vecXYZ.z = (galRadius/numSpheres*i) * FastMath.sin(lat) * jitter(galRadius/numSpheres*i);
    
                            if (vecXYZ.x > maxX || vecXYZ.x < minX)
                                if (vecXYZ.x < minX) minX = (int) vecXYZ.x;
                                else maxX = (int) vecXYZ.x;
    
                            if (vecXYZ.y > maxY || vecXYZ.y < minY)
                                if (vecXYZ.y < minY) minY = (int) vecXYZ.y;
                                else maxY = (int) vecXYZ.y;
    
                            if (vecXYZ.z > maxZ || vecXYZ.z < minZ)
                                if (vecXYZ.z < minZ) minZ = (int) vecXYZ.z;
                                else maxZ = (int) vecXYZ.z;
    
                            Star ns = new Star();
                            stars.add(ns.Star(vecXYZ.x, vecXYZ.y, vecXYZ.z));
                        }
                    }
                }
            }
            this.setMaxSize(maxX, maxY, maxZ);
            this.setMinSize(minX, minY, minZ);
            this.computeSizes();
        }
    
        /* Jitter coordinates so it looks more like a galaxy than spheres
        * +- half the radius
        *
        * @param radius
        *   radius of the sphere
        */
        private float jitter(float radius) {
            // jitter a point + - the radius
            return (radius/2) * (FastMath.nextRandomFloat() * (FastMath.nextRandomFloat()>.5f ? 1 :-1));
        }
    
        public int getNumSpheres() {
            return this.numSpheres;
        }
    
        public int getStarsBySpheres() {
            return starsBySphere;
        }
    }
    Now, in the main class, if I want to retrieve "starsBySpheres", I simply would call galaxy.getStarsBySpheres IF I would know beforehand what kind of galaxy the program will generate. But I can't.

    Here in the main class I want to use those fields defined in Galaxy, I can't.
    Java Code:
                    case 3: // Ellipsoid Galaxy
                        tag = (int) (galaxy.getNumSpheres()>1 ? (maxStarsScreen/galaxy.getNumSpheres()) :  maxStarsScreen/galaxy.getStarsBySpheres());
                        changeSphereAt =  maxStarsScreen / galaxy.getNumSpheres();
                        atSphere = 1;
                        tagStop = 0;
                        break;
    It doesn't work because galaxy doesn't have those methods.

    The only way I found to fix this is by declaring each type of galaxy beforehand like so:
    Java Code:
        protected Galaxy galaxy;	// The new galaxy class
        protected Elliptical eGalaxy;	// The new galaxy class
        protected Spiral sGalaxy;	// The new galaxy class
        protected Barred bGalaxy;	// The new galaxy class
    Then later on do this:
    Java Code:
        private void makeGalaxyStuff() {
            switch (defGalaxy()) {
                case 1:
                    sGalaxy = new Spiral(g, galaxyStars);
                    galaxy = sGalaxy;
                    break;
                case 2:
                    bGalaxy = new Barred(g, galaxyStars);
                    galaxy = sGalaxy;
                    break;
                case 3:
                    eGalaxy = new Elliptical(g, galaxyStars);
                    galaxy = sGalaxy;
                    break;
            }
            g.bigBang();
        }
    Oddly enough, it works. I was expecting an error somehow when using galaxy = sGalaxy or any of the other types (barred or spiral).

    I can run the program fine (although it crashes but that's unrelated). So yeah, I could use it that way, but I'm worrying if that's the best way. Even though I'm only using (instantiating, filling and using) one type of galaxy each run, the overhead by declaring the other types shouldn't cause problems or eat memory.

    So in a sense I think I answered my own question... :/ Maybe I'm worrying for nothing. LoL

    Do you think I could run into problems by using galaxy = bGalaxy? I know that it extends galaxy, but I'm not sure if it's safe.

  4. #4
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    I'd say you possibly have your areas of responsibility a bit muddled somewhere if you need to know the type of the galaxy to actually do certain things.

    Why do you need to know the particular data for an eliptical galaxy?
    Could you restructure things such that that data does not have to escape the class?
    Is it for drawing, processing, what?

  5. #5
    MadJack is offline Member
    Join Date
    Sep 2010
    Location
    Qc
    Posts
    31
    Rep Power
    0

    Default

    Quote Originally Posted by Tolls View Post
    I'd say you possibly have your areas of responsibility a bit muddled somewhere if you need to know the type of the galaxy to actually do certain things.
    Isn't it why we do "Class ... extends ..." because one class related to another does things differently, but still has enough communal data to be considered part of the same whole?

    Why do you need to know the particular data for an eliptical galaxy?
    Could you restructure things such that that data does not have to escape the class?
    The Barred galaxy is also doing things differently, I didn't put the code here so not to be redundant. But each galaxy type does differs from the other. That's why they're extending Galaxy. I'm not sure what you're implying by "escape the class". But again, isn't it why we extend base classes?

    Maybe I'm confused on that subject.

    Is it for drawing, processing, what?
    For pinning the galaxy's stars on the canvas, I need specific info for each type. For the elliptical, since its algorithm is very different from the other two, I need to know the number of spheres that were used to make it up.

    But those cases are for a specific reason. When the player is inside the Octree, I don't use the formulas (as seen above) to draw the stars. I simply paint what's inside the leaf and that's that. But when the player moves out of the Octree or finds himself in an empty leaf, I draw a certain number of stars (depending on computing power of the computer) that will make an outline of the whole galaxy. This will also be used to give an overview map at some point (when user presses M or somesuch).

    But even if I rework those galaxy types, I don't see how it would change the problem. I would still have to declare each type of galaxy and at some point; if or switch through them to do what has to be done.

    Or am I missing something?

  6. #6
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    So it is to do with how you draw the galaxy, and what gets drawn.

    Would it make sense to move the calculation code that is specific to a particular class into that class, so you don't need to getNumSpheres() at all. The Elliptical class would do all that and return something standard that represents what can be "seen" by the user. This would apply to all the classes then. Something like a getVisibleStars() method, which would be on Galaxy, but implemented by the subclasses in their own particular way.

    This is what I mean by not letting the type specific data escape the class. If all that is actually needed from the galaxy subclasses is some list of visible stars then that should be the method provided...there is no need to know the inner workings.

    Think how Collections work. With a List<Something> we don't need to know precisely how add() works, we just need to know it will add Something to the List (whether ArrayList, LinkedList, whatever).

  7. #7
    MadJack is offline Member
    Join Date
    Sep 2010
    Location
    Qc
    Posts
    31
    Rep Power
    0

    Default

    I see your point, and it's the right way to go.

    I should just poll the galaxy so it spews me an ArrayList<Star> that I can manipulate as I wish.

    Thinking about it, I'm already doing that exactly, but in the wrong way. So from what I can see I won't even need to "use" a galaxy type. I'll just do it internally from the Galaxy class, which will itself call the right sort of galaxy then finally return what I need... Yeah.

    Thanks. :)

  8. #8
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    Yep, that's pretty much it.

    If there's "standard" stuff that each Galaxy class does to create the list then you can give Galaxy a method getVisibleStars(), which can call a protected abstract method that does the class-specific calculations. If there is no standard work then the simplest is to make Galaxy abstract and make the getVisibleStars() method abstract and leave it all up to the sub classes.

  9. #9
    MadJack is offline Member
    Join Date
    Sep 2010
    Location
    Qc
    Posts
    31
    Rep Power
    0

    Default

    Exactly.

    Although my problem right now is to have a working (doing a better revision of it) Octree, I will definitively remodel the galaxy classes. Also, due to my lack of experience I'm a bit struggling with subclassing, superclassing and all that. But I'm confident I'll untangle that whole thing in my head at one point or another.

  10. #10
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,006
    Rep Power
    20

    Default

    You've done better than most we see in here...

    And as for "Octree", I'll just sit here and nod and smile blankly.
    :)

  11. #11
    MadJack is offline Member
    Join Date
    Sep 2010
    Location
    Qc
    Posts
    31
    Rep Power
    0

    Default

    LoL :D

    Thanks for the nice comment.

    If you'd like a "demo" I've got a working rar'ed jar on my site. It's not much actually, but you can move a "ship" around while it changes leaf and display stars in that leaf. If you move out of any leaf or are in an empty one, it'll show the outline of the galaxy. That version is 3 days old, but unfortunately I wasn't happy with the way it was working, so now it barely loads. lol

    Anyway, the uploaded version is buggy, but runs. ;)

    Drop me a PM if you want to check it out and I'll link you.

  12. #12
    MadJack is offline Member
    Join Date
    Sep 2010
    Location
    Qc
    Posts
    31
    Rep Power
    0

    Default

    Took more time than I expected to get to it, but it's done. Took me barely a couple of hours (maybe a bit more) to do it too.

    Now, it seems there is something not playing nice... I'll take a look at it tomorrow. I need some Zzz.

    I have to admit though that I'm pretty happy with the changes. It is a lot more cleaner and the segregation is helping. Less clutter, more visibility into the code and what everything is doing since pertinent information is in its class rather than haphazardly sprinkled here and there, long long series of lines of code where they basically don't belong.

    Anyway.

    Thanks Tolls for the pointers.

    PS: I plan to put a little pre-pre-alpha preview soon for you guys to look at even though I'm not too inclined on "leaking" my code. Let's just say that worries me a bit. For some reason.

Similar Threads

  1. Extending Classes and What is Necessary
    By GavinCash in forum New To Java
    Replies: 10
    Last Post: 10-11-2010, 07:07 AM
  2. Got confused with extending classes.
    By nethz13 in forum New To Java
    Replies: 7
    Last Post: 04-19-2010, 12:19 AM
  3. OOP Question re. private variables and extending classes
    By ImplicitCharm in forum New To Java
    Replies: 7
    Last Post: 07-28-2009, 03:46 PM
  4. Using 2 Classes= Controller x Definition
    By Bascotie in forum New To Java
    Replies: 35
    Last Post: 05-13-2008, 11:05 PM
  5. [SOLVED] Problem with extending classes...
    By Bizmark in forum New To Java
    Replies: 4
    Last Post: 04-07-2008, 11:21 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •