Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (523)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (592)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  A need for const?  (Read 7196 times)
0 Members and 1 Guest are viewing this topic.
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Posted 2003-08-12 20:36:40 »

Now I may be totally off the mark here, so maybe people can put me straight..

Imagine the handy little class 'Vector2f', just a simple little math class. Now in C++ I'd happily write:
1  
const Vector2f getPosition();

to get an objects position, safe in the knowledge that who ever is calling the method can't tinker with the returned object. All well and good. But the Java equivilent would be without any sort of 'const' modifier, and so open up the class to be modified in an unintended way, bypassing the intended set method.

'final' to the best of my knowledge, just makes the reference final, not the actual data, and is therefore not a substiture. So the alternative would be
1  
void getPosition(Vector2f dest);

and having a blank object into which the new information is copied. That or return a copy, but both of these need an extra object to be created just to hold what will likely be a temporary result.

Now I may be being overly paranoid about the GC, but this is getting to be really annoying. I don't like possibly creating hundreds of tiny little objects per frame, and the alternative of keeping them around (or a small number of temporary ones around and reusing them) gets ugly when used to any large extent.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline Athomas Goldberg

Junior Devvie




Grrrrrr...


« Reply #1 - Posted 2003-08-12 21:41:25 »

If the Vector2f class is yours you may want to consider creating an immutable version of it. Something like:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
public interface Vector2f {
    public float getX();
    public float getY();
    // other methods
}

public class ImmutableVector2f implements Vector2f {

    private final float x;
    private final float y;
    public ImmutableVector2f(float x, float y) {
    this.x = x;
    this.y = y;
    }

    public float getX() {
    return x;
    }

    public float getY() {
    return y;
    }
}

public class MutableVector2f implements Vector2f {
    private float x;
    private float y;
    public MutableVector2f(float x, float y) {
    this.x = x;
    this.y = y;
    }

    public float getX() {
    return x;
    }

    public float getY() {
    return y;
    }
   
    public void setX(float x) {
    this.x = x;
    }

    public void setY(float y) {
    this.y = y;
    }
}


It's not quite the same as const, but it gets you at least part of the way there.

Athomas Goldberg
Project Lead / Wildcard
Game Technologies Group
Sun Microsystems, Inc.
Offline Athomas Goldberg

Junior Devvie




Grrrrrr...


« Reply #2 - Posted 2003-08-12 21:43:47 »

Oops. disregard my last missive. I misread your post Smiley

Athomas Goldberg
Project Lead / Wildcard
Game Technologies Group
Sun Microsystems, Inc.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #3 - Posted 2003-08-12 23:06:35 »

There are little tricks you can do.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
public class Vector2F
{
      int getX() { ... }
      int getY() { .. }
}

public class MutableVector2F extends Vector2F
{
      void setX(int x) { ... }
      void setY(int y) { ... }
}

public class MyClass
{
      private MutableVector2F myVector;
     
      public Vector2F getPosition()
      {
            return myVector;
      }
}


You're returning your vector truncated as the immutable base class. Only you can (honestly) alter it. You could take it one step further and make MutableVector2F a private class of your class.

That offers the same protection as C++ does, generally. It prevents honest use of your class from accidentally damaging things. Dishonest use is possible, sure, just cast it down to the mutable form. But that's deliberate, and if you're own code is doing that, then something else is wrong. If someone else is deliberately trying to mess up your vector, then C++ offers you the same shakey safety, casting away constness is very easy.

Incidentally a lot of Swing classes take it to the extreme and return a copy of the object. Ugh.
Offline Athomas Goldberg

Junior Devvie




Grrrrrr...


« Reply #4 - Posted 2003-08-13 01:17:44 »

Since we're on the subject of tricks you could make your an inner class with private member variables, which would only be accessible to the outer class, like so:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
public class Vector2F {
  public float getX() { ... }
  public float getY() { .. }
}

public class MyClass {

private MyVector2f position = new MyVector2f();

public void setPosition(float x, float y) {
        position.x = x;
        poxition.y = y;
}

public Vector2f getPosition() {
        return position;
}

private static class MyVector2f extends Vector2f {
        private float x;
        private float y;
        public float getX() { return x; }
        public float getY() { return y; }
}
}

Unlike the previous example, the Vector2f returned from getPosition() can't be cast into a mutable form, but thanks to scoping your outer class can modify it. This of course assumes that Vector2f isn't final or contains so many methods that overriding it this way is a pain in the @ss. It does however do what you want it to, namely prevent someone else from modify the object while giving your class the ability to, if in a somewhat convoluted way.

Athomas Goldberg
Project Lead / Wildcard
Game Technologies Group
Sun Microsystems, Inc.
Offline kevglass

« JGO Spiffy Duke »


Medals: 205
Projects: 24
Exp: 18 years


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #5 - Posted 2003-08-13 04:28:11 »

All this is besides the point that (C++ style) const would be damn useful. I've often wonder why Java didn't pick it up from C++ on the way...

Does anyone know why?

Kev

Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #6 - Posted 2003-08-13 05:57:40 »

Quote

This of course assumes that Vector2f isn't final or contains so many methods that overriding it this way is a pain in the @ss. It does however do what you want it to, namely prevent someone else from modify the object while giving your class the ability to, if in a somewhat convoluted way.


Thats quite a neat trick, I'll probably use that at some point, but in this actual case there are a lot of methods and to have to do this everywhere needed would be a large amount of work for not enough gain :-/

Would be nice to get a proper 'const', but I guess most people think that returning a copy is an acceptable solution  :-[

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline princec

« JGO Spiffy Duke »


Medals: 422
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #7 - Posted 2003-08-13 08:50:11 »

Nah, returning a copy is a sucky solution Sad Const is a handy keyword which is really a shortcut for creating tons of irritating get methods and read-only interfaces.

I like programming shortcuts. Every byte I type is a byte that can go wrong :/

Cas Smiley

Offline cfmdobbie

Senior Devvie


Medals: 1


Who, me?


« Reply #8 - Posted 2003-08-13 09:47:11 »

Const was left out because it was deemed unnecessary, and a complication.  Much like unsigned, enum, generics, multiple inheritance and all the other interesting stuff people still clamour to add!

Vote here:

http://developer.java.sun.com/developer/bugParade/bugs/4211070.html

Hellomynameis Charlie Dobbie.
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #9 - Posted 2003-08-13 10:29:13 »

const is nice, but it does complicate things. I think Sun just wanted to keep Java slim and straightforward. Although I do think the omission of unsigned was a complete sin Smiley
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Athomas Goldberg

Junior Devvie




Grrrrrr...


« Reply #10 - Posted 2003-08-13 11:33:48 »

Quote
Much like unsigned, enum, generics, multiple inheritance and all the other interesting stuff people still clamour to add!

Well, at least enums and generics will finally be showing up in 1.5. And const has been set aside as a keyword in Java, so... who knows?

That said, I wouldn't hold my breath waiting for multiple inheritence. Smiley

Athomas Goldberg
Project Lead / Wildcard
Game Technologies Group
Sun Microsystems, Inc.
Offline cfmdobbie

Senior Devvie


Medals: 1


Who, me?


« Reply #11 - Posted 2003-08-13 11:47:34 »

No, agreed!  Multiple inheritance causes more problems than it's worth (although I can come up with persuasive reasons to have it).  Operator overloading is another thing I'm glad to see the back of, after a fashion!

Unsigned really used to annoy me - I mean, what's an unsigned byte?  That just doesn't make any sense!  You get used to it after a while though. Roll Eyes

Hellomynameis Charlie Dobbie.
Offline Athomas Goldberg

Junior Devvie




Grrrrrr...


« Reply #12 - Posted 2003-08-13 11:54:11 »

Quote
Thats quite a neat trick, I'll probably use that at some point, but in this actual case there are a lot of methods and to have to do this everywhere needed would be a large amount of work for not enough gain :-/

Ooh, wait... Here's another flavor of the solutions:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
public class Vector2F {
 public float getX() { ... }
 public float getY() { .. }
 public void setX(float x) throws ImmutableException { ... }
 public void setY(float y) throws ImmutableException { ... }

 // bunch o' other methods
}  
 
public class MyClass {
 
 private MyVector2f position = new MyVector2f();
 
 public void setPosition(float x, float y) {
  position.secretSetX(x);
  poxition.secretSetY(y);
 }
 
 public Vector2f getPosition() {
  return position;
 }
 
 private static class MyVector2f extends Vector2f {
  public void setX(float x)
   throw new ImmutableException();
  }
  public void setY(float y)
   throw new ImmutableException();
  }
  private void secretSetX(float x) {
   try {
    super.setX(x);
   } catch(ImmutableException e) { // do nothing }
  }
  private void secretSetY(float y) {
   try {
    super.setY(y);
   } catch(ImmutableException e) { // do nothing }
  }
 }
}  


Same result as previous solution, but all you have to do is reimplement your "set" methods.

You can also make the MyVector2f and the "secret" methods package local, in which case you'd only have to implement MyVector2f once per package that was going to use it.

I'm a stong believer in scoping classes to the scope of their use. If a class is only used within another class, I make it an inner class. If it's only used by other classes in a given package, I make it package local, etc, etc But that's another debate altogether.

Athomas Goldberg
Project Lead / Wildcard
Game Technologies Group
Sun Microsystems, Inc.
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #13 - Posted 2003-08-13 11:56:06 »

Quote

Well, at least enums and generics will finally be showing up in 1.5. And const has been set aside as a keyword in Java, so... who knows?


Yes, but then again... so it goto... Shocked

Quote
Operator overloading is another thing I'm glad to see the back of, after a fashion!


1  
String whatAbout = "String " + "concanenation?";

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #14 - Posted 2003-08-13 11:57:39 »

except your setX() never actually sets anything, it just throws the exception. So your secretSetX() won't actually set anything either.
Offline Athomas Goldberg

Junior Devvie




Grrrrrr...


« Reply #15 - Posted 2003-08-13 12:00:10 »

Personally, I think the existance of the "Immutable" design pattern and the need for convoluted solutions like those detailed above, should be argument enough for adding const, but that's just me. I'm sure there are a host of reasons, technical and otherwise, for it's exclusion, but it certainly would be nice.

Athomas Goldberg
Project Lead / Wildcard
Game Technologies Group
Sun Microsystems, Inc.
Offline Athomas Goldberg

Junior Devvie




Grrrrrr...


« Reply #16 - Posted 2003-08-13 12:05:50 »

Quote
except your setX() never actually sets anything, it just throws the exception. So your secretSetX() won't actually set anything either.

secretSetX() (in MyVector2f) calls super.setX() (setX() in Vector2f) which presumably has some code to replace the "..." shorthand to actually set the value of X.

Athomas Goldberg
Project Lead / Wildcard
Game Technologies Group
Sun Microsystems, Inc.
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #17 - Posted 2003-08-13 12:10:13 »

One of the biggest reasons for having const is passing arguments by const reference. Without pass by reference in Java, const loses a lot of use.

Even Orangy Tang's example is usually not done quite that way in C++, usually a const reference is returned.

Quote

secretSetX() (in MyVector2f) calls super.setX() (setX() in Vector2f) which presumably has some code to replace the "..." shorthand to actually set the value of X.


Ah yup, just being stupid. Too early in the morning for me Smiley
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #18 - Posted 2003-08-13 12:30:16 »

Quote
One of the biggest reasons for having const is passing arguments by const reference. Without pass by reference in Java, const loses a lot of use.


Deftly stepping around the whole 'Java passes everything by value' argument, how is the C++ code:
void Class::SomeFunc(Vector2f* position);
any different from Java:
void someFunc(Vector2f position);
? This is another area that i feel like const would be handy - I don't want to pass in the actual object because i don't want it changed, yet making a copy is a waste of time. A simple const modifier is exaxtly whats needed (could this be a compile time check, and thus be added to the language without too much fuss?). Instead of the nice simple
void someFunc(const Vector2f position);
I end up with the rather more ugly:
void someFunc(float x, float y);

Quote
Even Orangy Tang's example is usually not done quite that way in C++, usually a const reference is returned.


Well really its not what i usually come across in C++ code, its usually something like
void Class:GetPos(Vector2f* pos);
which is nice because the caller can just create the object on the stack and let it quietly go out of scope without worrying about a GC sticking its neak in....

Edit: its not a simple compile time modification, you can't tell if a given method will modify the object or not until runtime.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #19 - Posted 2003-08-13 13:07:28 »

Quote


Deftly stepping around the whole 'Java passes everything by value' argument, how is the C++ code:
void Class::SomeFunc(Vector2f* position);
any different from Java:
void someFunc(Vector2f position);


Generally they're not that different. In both cases you're passing in a copy of the pointer/reference to the object. Since it's a new copy, you can't cause the original pointer/reference to refer to a new object.

But that's a C++ pointer, not reference.

with

void foo(SomeObject &bar);

you've passed in the actual object via reference. This method has free reign on this object, including causing it to be an entirely new object altogether. Sometimes you want that sometimes you don't.

void foo(const SomeObject &bar);

Same thing, but bar can't be altered in anyway. No expensive copying, you get the object to work with and it's safe. Everyone's happy.

This is essential when templates come into play

template <class T>
void foo(const T &bar);

that T could be a lowly byte to a gigantic object. Since you don't know, you really don't want to copy it, const reference passing becomes crucial.

And of course, being C++, there's about a billion other combinations, const pointers, pointer references, pointers to pointers, on and on.

Quote

Well really its not what i usually come across in C++ code, its usually something like
void Class:GetPos(Vector2f* pos);
which is nice because the caller can just create the object on the stack and let it quietly go out of scope without worrying about a GC sticking its neak in....


Why though? just do

const Vector2f &getPos() const;

no object creation takes place at all, and everyone gets a loot at the object in a safe way.
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #20 - Posted 2003-08-13 13:15:59 »

I think you're missing my point somewhat - I'm perfectly happy with the myrad of options that C++ presents, but rather miffed that providing similar safety in Java involves a large amount of tedious leg work Sad

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #21 - Posted 2003-08-13 13:26:14 »

You presented generally poor C++ code and asked why it wouldn't be done that way, I answered.

Adding C++ style const to Java wouldn't be a simple addition, and it's debatable how useful it'd even be considering how the rest of Java works.

Quote

Edit: its not a simple compile time modification, you can't tell if a given method will modify the object or not until runtime.

C++ compilers do it all the time, they aren't involved in the runtime process at all.
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #22 - Posted 2003-08-13 13:42:25 »

Most of the snippits are examples that i've seen in other C++ libs, mainly MFC, I'll be the first to admit that my C++ knowledge is not as complete as i'd like.

As for compile time const checking, C++ compilers don't have to deal with dynamically loaded classes.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #23 - Posted 2003-08-13 14:10:30 »

(and I think we're officially off topic now Smiley )

I don't see what dynamically loading the classes has to do with compile time const checking. For one most C++ implementations have support for dynamically loaded classes/libraries, it's just not universal like Java's is.

I'd imagine it's a matter of adding an additional flag to the symbol table, and checking the flag at each assignment operation. Or there's probably a better way as that'd likely be expensive.

But if all classes come from the same compiler, then I don't see how the fact that they're dynamically loaded matters.

C++'s const checking is far from perfect. Like I said earlier, you can explicitally cast away constness (something the compiler's aware of and is ok with) or it's also possible to sneak constness off in ways the compiler doesn't realize. In the end the developer still has to have a head on his shoulders Smiley All these things like const are just there to help, not be absolute.
Offline Orangy Tang

JGO Kernel


Medals: 56
Projects: 11


Monkey for a head


« Reply #24 - Posted 2003-08-13 14:22:12 »

Well, as an example: I'm using an imaginary lib that has Vector2f, which has a .angleTo(Vector2f) call. Now in a function i'm using what is supposed to be a const vector, and since the angle function returns the angle and leaves the vector alone all is good.

But then on another system the program is run, and the same lib is using a different version which (for reasons unknown) normalises the vectors while calculating the angle - the const object has been changed and theres no way for the compiler to pick up on it.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #25 - Posted 2003-08-13 15:55:54 »

The interface to his method needs to declare that. He either accepts a const vector or a nonconst vector, and that generally indicates if the object could or won't change. If his interface declares a nonconst argument, it's an error to send a const argument to that method, either runtime or compile depending on when it could be caught.

It's sort of like using say java.awt.Color.RED in Java 1.3. That field doesn't exist, it's a compile time error. But if you took a 1.4 class that uses Color.RED in a 1.3 JVM, it becomes a runtime error and the jvm properly catches it. It'd (I assume) do the same for const.

But again, const is just the language/compiler trying to help out, it's not absolute. If you're working with some unknown library that accepts a const vector, for all you know he had to write in some kind of kludge in that method which removes the constness and changes your vector. Maybe he did that to fit his own needs and didn't consider other users. That's really terrible programming, but it happens.
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #26 - Posted 2003-08-13 16:08:12 »

What would a const system do to reflection, jni and final?
Offline cfmdobbie

Senior Devvie


Medals: 1


Who, me?


« Reply #27 - Posted 2003-08-13 16:11:43 »

Quote
But then on another system the program is run, and the same lib is using a different version which (for reasons unknown) normalises the vectors while calculating the angle - the const object has been changed and theres no way for the compiler to pick up on it.


Couldn't you make the const-ness of the arguments and return types an integral part of the method signature?  Also, allow subclasses to offer the same or a more strict version of method args, and the same or less strict return values?

Hrm, actually I'm not sure that would be so useful.  Needs some thought...


Quote
Yes, but then again... so it goto... Shocked

Yeah, can't *wait* for that to be added! Roll Eyes

Quote
1  
String whatAbout = "String " + "concanenation?";

That's very well known, a specific case, and any confusion created is *totally* outweighed by its usefulness.  I disagree with user-generated operator overloading because people start creating things like:
1  
2  
3  
4  
boolean result = "Lesser" < "or Greater?" ;
Socket s = socket1 + socket2 ;
HostName host ; PortNumber port ; URL url = host + port + "/index.html" ;
Texture multiTexture = texture1 & texture2 ;

You give people an utterly misusuable tool, and they'll misuse it utterly!  You know they do!

Hellomynameis Charlie Dobbie.
Offline tortoise

Junior Devvie




<3 Shmups


« Reply #28 - Posted 2003-08-13 16:19:52 »

Quote

You give people an utterly misusuable tool, and they'll misuse it utterly!  You know they do!


And operator overloading can be used very elegantly, and improve efficiency to boot. It's a double edged sword, no doubt.
Offline Preston

Senior Devvie


Medals: 4



« Reply #29 - Posted 2003-08-14 10:45:40 »

On http://developer.java.sun.com/developer/community/chat/JavaLive/2003/jl0729.html the same question like here as been asked (and answered by a SUN engineer) :
Quote
Q: Is there any plan to support the const keyword in the future, as in C++? If not, is there a reason?

Josh Bloch: We do not have plans to add support for the const keyword to the Java language. It was a mixed blessing in C++; as you know, it's merely advisory, and can cast on or off. Gosling hated it, and did final instead. What you really want is "immutable," but it's a research problem to make this work properly.

Pages: [1] 2
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

SHC (24 views)
2014-11-25 13:00:59

SHC (23 views)
2014-11-25 12:53:45

Norakomi (21 views)
2014-11-25 12:26:43

Gibbo3771 (22 views)
2014-11-24 20:59:16

trollwarrior1 (36 views)
2014-11-22 13:13:56

xFryIx (74 views)
2014-11-13 13:34:49

digdugdiggy (52 views)
2014-11-12 22:11:50

digdugdiggy (46 views)
2014-11-12 22:10:15

digdugdiggy (41 views)
2014-11-12 22:09:33

kovacsa (68 views)
2014-11-07 20:57:14
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 23:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 23:36:02

List of Learning Resources
by Longor1996
2014-08-16 11:40:00

List of Learning Resources
by SilverTiger
2014-08-05 20:33:27

Resources for WIP games
by CogWheelz
2014-08-01 17:20:17

Resources for WIP games
by CogWheelz
2014-08-01 17:19:50

List of Learning Resources
by SilverTiger
2014-07-31 17:29:50

List of Learning Resources
by SilverTiger
2014-07-31 17:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!