Announcement

Collapse
No announcement yet.

Java problem - help please!

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Java problem - help please!

    This is doubtless incredibly basic, but it's typical of the stuff I'm tripping up on while adapting to OOP. Please don't be nasty.

    Let's say that my main routine in my RunSea object instantiates an object of class Sea called atlantic.

    Sea atlantic= new Sea();

    (Earlier is the declaration: public Sea atlantic; I've tried having this in and out, and static present or not and it doesn't seem to make a difference.)

    Within the Sea class, I instantiate an object of class Submarine called mySub.
    There's actually an array of Submarine objects, but I'm assuming my problem applies to a single sub.

    The Submarine class has a method called moveSub which wants to access a method in the atlantic object called checkMove. This determines whether a given location in altantic is free to move into.

    The moveSub method in mySub can't access the atlantic object. The complier says "Cannot find symbol - variable atlantic". I can shut the compiler up by declaring one but (understandably) just get a null object pointer error at runtime.

    The atlantic.checkMove method is public but I don't think that's the point. The mySub object can't see the atlantic object. I think.

  • #2
    Your problem is that the submarine doesn't have a reference to atlantic. Presumably, the idea is that you could have multiple seas, so one way to design this would be to tell a submarine what sea it is in on construction:

    Code:
    class Submarine {
        private Sea containingSea;
    
        public Submarine(Sea where) {
            containingSea = where;
            containingSea.addSubmarine(this);
        }
        
        public void moveSub(int lat, int lon) {
            if (!containingSea.checkMove(lat, lon) {
                /* resolve the situation somehow */
            } else {
                /* update this Submarine to represent the move */            
            }
        }
    
    }
    
    class Sea {
        private List subs;
        
        public void addSubmarine(Submarine sub) {
            subs.add(sub);
        }
        
        public boolean checkMove(int lat, int lon) {
            /* somehow determine if it is a valid move */
        }
        
    }
    
    public class RunSea {
    
        public static void main(String[] args) {
            Sea atlantic = new Sea();
            Submarine mySub = new Submarine(atlantic);
        }
        
    }

    Comment


    • #3
      What Kuci said.

      Also, consider implementing it with closures.
      "The issue is there are still many people out there that use religion as a crutch for bigotry and hate. Like Ben."
      Ben Kenobi: "That means I'm doing something right. "

      Comment


      • #4
        Some advice:

        static can only be applied to the declaration of a variable or method within a class - it cannot be applied to variables declared inside of a method body. A static variable or method is not associated with any instance of that class. So, if you added 'static String foo = "bar";' to Sea, then there would only ever be one foo, and if any of the methods of Sea changed it, they would all see the change.

        public, when applied to a declaration of a variable or method within a class (but not enclosed in a method!), permits code from outside that class to access that variable by name. For a non-static method like addSubmarine, this is what permits the Submarine(Sea where) constructor to call containingSea.addSubmarine(this). If addSubmarine were private, then only a method in Sea would be able to call it.

        Neither of these keywords can be used in a variable declaration inside of a method body. All such variables are local to the method body.

        Comment


        • #5
          Thanks, Kuci.

          I'll try and relate this to my coding. We haven't been demonstrated this technique yet, or the use of the keyword 'this', but I think I follow what you've done.

          I've instantiated my sub from the Sea class rather than the RunSea class. I don't know if that makes a difference. I might look to do it in the RunSea instead if that's better practice. It's early days for me.
          Last edited by Cort Haus; October 23, 2010, 06:23.

          Comment


          • #6
            re: this

            Basically, every class Foo has a hidden member variable of type Foo called 'this'. That member variable always references the object it is a member of. So, "this" (which can only be used inside non-static functions) always refers to the current object that you are "in". So if I call mySub.moveSub(x, y), while I'm inside of moveSub "this" will refer to mySub.

            An example of how you would use the pattern I showed above from within a method of Sea:

            Code:
            class Sea {
                private List subs;
                
                public void addSubmarine(Submarine sub) {
                    subs.add(sub);
                }
            
                public void makeSubmarineAndThenAddIt() {
                    Submarine mySub = new Submarine(this);
                }
                
                public boolean checkMove(int lat, int lon) {
                    /* somehow determine if it is a valid move */
                }
                
            }

            Comment


            • #7
              Shouldn't makeSubmarineAndThenAddIt actually add it?
              "The issue is there are still many people out there that use religion as a crutch for bigotry and hate. Like Ben."
              Ben Kenobi: "That means I'm doing something right. "

              Comment


              • #8
                It's a stealth sub and noone knows where it is

                Totally off topic, is it really a good idea to have Submarine as part of a specific ocean ? It would give some headache when it move from one ocean to another. I mean, you have to scarp it in one and rebuild it in another - can't be cost effective - especially given current british economy.
                With or without religion, you would have good people doing good things and evil people doing evil things. But for good people to do evil things, that takes religion.

                Steven Weinberg

                Comment


                • #9
                  Originally posted by Asher View Post
                  Shouldn't makeSubmarineAndThenAddIt actually add it?
                  The Submarine constructor adds it, remember?

                  Comment


                  • #10
                    Originally posted by Kuciwalker View Post
                    The Submarine constructor adds it, remember?


                    That is so wrong that you should be burned on a stake.
                    With or without religion, you would have good people doing good things and evil people doing evil things. But for good people to do evil things, that takes religion.

                    Steven Weinberg

                    Comment


                    • #11
                      Oh no, I named the method a little poorly, it should be called "makeSubInThisSea"

                      Comment


                      • #12
                        Originally posted by Kuciwalker View Post
                        Oh no, I named the method a little poorly, it should be called "makeSubInThisSea"
                        Honestly, I really don't care what you call it - having constructors with side effects is the sign of a very bad programmer. You don't even have the excuse of being an inexperienced such, so it's simply retarded.
                        With or without religion, you would have good people doing good things and evil people doing evil things. But for good people to do evil things, that takes religion.

                        Steven Weinberg

                        Comment


                        • #13
                          I sadly concur with BlackIce. A constructor should allocate an object and any necessary members only.

                          For operational things, like placing the sub in the sea, this should be done via a separate method.

                          Remember that the main purpose of OO code is enhanced reusability and maintenance. Muddling up the constructors with something other than simple object initialization is a no-no.


                          Code:
                          class Sea {
                              private List subs;
                              
                              public void addSubmarine(Submarine sub) {
                                  subs.add(sub);
                              }
                          
                              public void makeSubmarineAndThenAddIt() {
                                  addSubmarine(new Submarine(this));
                              }
                              
                              public boolean checkMove(int lat, int lon) {
                                  /* somehow determine if it is a valid move */
                              }
                              
                          }
                          Now it makes sense.
                          Remove the adding from the sub constructor. It makes zero sense for the sub's constructor to add itself to a sea.

                          But I don't like it, because then whoever calls the makeSubmarineThenAddIt doesn't have a reference to the submarine it just added.

                          So:
                          Code:
                          class Sea {
                              private List subs;
                              
                              public void addSubmarine(Submarine sub) {
                                  subs.add(sub);
                              }
                          
                              public Submarine makeSubmarineAndThenAddIt() {
                          	Submarine newSub = new Submarine(this);
                                  addSubmarine(newSub);
                          	return newSub;
                              }
                              
                              public boolean checkMove(int lat, int lon) {
                                  /* somehow determine if it is a valid move */
                              }
                              
                          }
                          "The issue is there are still many people out there that use religion as a crutch for bigotry and hate. Like Ben."
                          Ben Kenobi: "That means I'm doing something right. "

                          Comment


                          • #14
                            I sadly concur with BlackIce.
                            That's twice in same amount of days - hope that it isn't going to be a habit
                            With or without religion, you would have good people doing good things and evil people doing evil things. But for good people to do evil things, that takes religion.

                            Steven Weinberg

                            Comment


                            • #15
                              @Cort Haus, You may think that Kuci, Asher and I just have some academic brawl of what is the right method, but there is a little more in it than that.

                              Consider the situation where you for some reason needs a temp submarine - you use kuci's method to create that object. After doing what you want to do, you now have a ghost sub in the ocean. In C++ you will have a pointer to unallocated memory, and I guess the same goes for java, though, I'm not sure - no matter what, you have pointers to invalid data.

                              Well, you can of course solve the problem through an advanced destructor, but that I'm pretty sure that you don't want to do
                              With or without religion, you would have good people doing good things and evil people doing evil things. But for good people to do evil things, that takes religion.

                              Steven Weinberg

                              Comment

                              Working...