plee for Properties, Private Fields
BlitzMax Forums/BlitzMax Programming/plee for Properties, Private Fields
| ||
I'm back for a while from my jaunt into .netland. Anyway, now that I'm coding some blitzmas the main things I miss are private fields and properties. We've talked about this before, but I'd like to try again. Now, private fields can be evil, it is true. It's annoying when the field is there, you just can't access it. However, they serve a very good purpose - prevent the user from inadvertently setting the field to an invalid or null value. This will result in an exception somewhere along the line. It might not even show up except in rare circumstances, if the field is not used much. It is possible to prevent this by peppering your code with if statements checking the value. This is slower and ugly to boot. If a field is private then it can only be accessed from the class's methods which presumably deal with it in a safe manner. A well written class can guarrantee that the values of its fields will not be out of range. However, now with all these private fields if you want a reasonably direct method of modifying them, you need to create get/set proxy methods which rather clutter up the class. This is where properties come in. They allow get/set methods to look like fields. Most importantly, the set method can make sure the value of a field is not set to null. Properties are also useful for things that aren't even fields. For example I might make a 'Rectangle' class and have fields storing position and size. I could have a property "BottomRight", which returns and receives a point class. My suggestion for a syntax would be: Property BottomRight Method Get:Point() return Point.Create(x+w, y+h) End Method Method Set(val:Point) If val <> null Then w = val.x - x h = val.y - y Endif End Method End PropertyConverted by blitzmax compiler to: Method get_BottomRight:Point() return Point.Create(x+w, y+h) End Method Method set_BottomRight(val:Point) If val <> null Then w = val.x - x h = val.y - y Endif End MethodTo use the property: Print a.BottomRight.XConverted to: Print a.get_BottomRight().XOh, and constructors with parameters would be nice! To mark: Pretty please? should only take a day or two. Oh, I almost forgot, it'd be nice to have a "getter" attribute for fields which autocreates a get-only property. Also a 'property' attribute, which for non-base types makes sure it can't be nullable. This cuts down the majority of most get/set method clutter. |
| ||
I'm with you - after using .Net it all makes so much sense and gives your classes (or methods in this case) clarity. Anyway, time will tell. It's still a great language!! |
| ||
Second the request for private within classes (not only fields). The actual implementation that is needed makes extending of "information hidding" classes in modules very hard and tricky for users. As for the properties: would be nice but definitely no must-have. |
| ||
Private/protected fields would be very good. Along with interfaces. And overloading. And generics. |
| ||
Interfaces? is that somehow different from creating an abstract class? |
| ||
Yes. An interface is like a 'clean' version of multiple inheritance. You implement interfaces, and then you can request objects that implement a specific interface. E.g., IRenderable, IStreamable, IContainer, IDisposable, ICloneable, etc. If you wanted to clone something you would implement the ICloneable class, if you wanted forced disposal of resources you would implement IDisposeable, if you wanted container functionality in an object you would implement the IContainer interface, and so on and so forth. So yes, it's different. |
| ||
I still fail to see the purpose of properties, but private access modifiers and typesafe callbacks (delegates in .Net speak) would be wonderful. |
| ||
Yeah, I kind of forgot about interface - they are very nice too. Overloading would be awesome. Generics, well, generics are very cool. However, they are probably the most difficult things to implement, and they are mainly used to make collections specific. I think generics would take too much effort on mark's part. Constructors with parameters, private, protected, overloading, interfaces should take a week or so. Perhaps I am optimistic - I don't know how much time mark has in a week, what his usuall per day hourage is. The only language I've ever messed around with the insides had one of the best structures possible. You could even swap out certain sections of code and get it to compile other languages. I'd be glad if you could just implement privates, mark I'd be very glad, maybe exstatic if you could implement all the other stuff as well. Flameduck: Consider these two examples, which looks better? Properties are all about syntax sweetness. a.Speed += 1 a.SetSpeed(a.GetSpeed() + 1) |
| ||
a.AddSpeed(1) ------------------- Method IncreaseSpeed(amount:int) Speed:+amount End Method |
| ||
My proposition regarding properties (already suggested) is much simpler. Why not just treat properties as a pure shortcut for simple getters and setters? This is something I implemented myself in my compiler, and I quite like it.Type MyType Method GetColor%() ... End Method Method SetColor(col%) ... End Method End Type Local obj:MyType = New MyType obj.color = obj.color / 2 ' or of course, "obj.color :/ 2" ' Identical to ' obj.SetColor(obj.GetColor() / 2) Advantages : - it's crystal clear what you're doing, while using setters and getters obfuscate the code. - absolutely no unneeded syntax change Really, that can be added in a blink. I know, I did it. I still fail to see the purpose of properties Maybe you just need to use them. As a simple pragmatic point, do you really prefer "obj.SetColor(obj.GetColor() / 2)" over "obj.color :/ 2" ?If you find the first version more readable then you've managed to surprise me. As a second more general point, properties are a way to abstratc away data access. You don't care if some value of an object is computed, stored in a field or even fetched from a database, that's really none of your business (as a client). |
| ||
From the descriptions, Interfaces are the same as abstract types (ie only definition but no implementation). Interfacing like you mention it and how it is often used is impossible in BM anyway due to the missing support for multiple inheritance :-( |
| ||
I really would enjoy it if BlitzMax would some day support properties, method overloading, and operator overloading. Private members would be nice too, although supporting properties and overloading is more useful to me. |
| ||
Interfacing like you mention it and how it is often used is impossible in BM anyway due to the missing support for multiple inheritance :-( That's why I suggested it. To make it so that it's not impossible. Then again, given that BMax seems to be set in stone now (what happened to enums, eh?), it's probably highly unlikely we'll get anything good out of requests. |
| ||
Yes, koriolis's method is best, not even that hard to impelment. This is actually how .net does it - two methods per property and a bit of metadata defining the property. A practical example of private members is in a class i'm working right now - I've got a Paused field in my main game engine class. However I want the user to use the PAuse() and UnPause() methods because otherwise delta timing will get very messed up as it will think that the amount of time it was paused was one frame, so everything would shoot off in different directions very,very fast. With private fields the user would be forced to use the methods, which would properly reset the delta timing vars. With Properties it would actually look the same way as the user wants it to. |
| ||
This is actually how .net does it - two methods per property and a bit of metadata defining the property. And given that BlitzMax doesn't support reflection, metadata doesn't even enter into the equation here. So that really, really couldn't be easier to implement. It's one of those few features that have a very high "usefulness / implementation complexity" ratio. You hack the thing in a blink, and then goes "wow, this little thing is cool".We just have to convince Mark how much nicer this can make some code look. |
| ||
General idea for propertiesi.Speed = 50 If Speed is not a field of i Then If i has method SetSpeed Then i.SetSpeed( 50 ) Else Throw exception EndIf EndIf Print i.Speed If Speed is not a field of i Then If i has method GetSpeed Then Return i.GetSpeed Else Throw exception EndIf EndIf This is exactly how D does it. It's a very simple implementation of properties and works flawlessly. I don't see why it couldn't be added as syntactic sugar for BlitzMax. |
| ||
If the throw part refers to a compile time error, then that's exactly what I propose. That's now 3 votes for this implementation. And counting... (I hope) |
| ||
Yes, that would be a compile-time error. |
| ||
And counting... (I hope) Make it four. It seems very simple to implement and immensely useful. |
| ||
Im voting for interfaces. That doesn't just save code space, it makes the structure more flexible for a program. |
| ||
You got my vote! |
| ||
After looking over some stuff, this seems to be exactly how the EachIn functionality is handled. So not adding properties would just be absurd now that I think about it. |
| ||
I don't think I get it. You can allready do this:SuperStrict Type myt Field color:Int End Type Local cheese:myt = New myt cheese.color = 10 Print "Color: " + cheese.color cheese.color:/ 2 Print "Color: " + cheese.color Private Fields on the other hand... Yes Mama! |
| ||
Peter: The idea is that you do something while setting the property. For example, say you do something like i.References = 0 Now, when you do that, i.SetReferences( i% ) is called. Method SetReferences( i% ) _refs = i If _refs = 0 Then Do something EndIf End Method Or, the parenting situation: Type Entity Field _parent:Entity Field _children:TList = New TList Field _link:TLink Method SetParent( p:Entity ) If _link Then _link.Remove( ) _link = Null _parent = p If _parent Then _link = _parent._children.AddLast( Self ) EndIf End Method End Type Local e1:Entity = New Entity Local e2:Entity = New Entity e1.Parent = e2 ' Calls the above code to set the link, remove the old link, etc. - can't do that by just setting _parent |
| ||
Thanks! I get it. It's like VB 6. I allways hated the way those where autocreated, whenever I defined a field, so I hope this is not comming to BMax. If it's implemented as hidden methods, that I can then overload ( like New() and Delete() ), I guess it's ok, as long as it doesn't impact compilation and execution speed. ) |
| ||
Somehow I get the impression you either don't understand what I'm saying or you're wierd as all hell. |
| ||
Remind me not to spend more time on you Noel. It really is exausting how you can turn anything into an insult/conflict. I don't see anything wierd with what I wrote. |
| ||
Can't take a joke, Pete? O_o |
| ||
Jokes have to be funny, by definition. |
| ||
It's funny to me, therefore it is a joke. |
| ||
I think its the medication... |
| ||
Peter - its not really a replacement for fields, just a syntax sugar for ugly get/set methods. I hope bmax or the C compiler is smart enough to inline alot of the properties though. I know that in C# most of the get properties are inlined by the compiler I think constructors with parameters would also be very nice. Right now I'm making Create functions, however, these functions are inheritable, and there is no overloading. So I'm limited to only one return type. Now I have to make "CreatePoint:TPoint" functions.... Plus this means you could call TAtom.CreatePoint:TPoint, which is just plain odd. [edit] I just realized i could make these functions outside of the classes so they wouldn't looks so bad. Still. |
| ||
Bump. |
| ||
Long responses such as this from BRL is why I still use blitz. Oh, wait... *A bump of optimistic hope* |
| ||
Funny how earlier skidracer said he wanted specific criticism, and then he ignores stuff like this. |
| ||
Welcome to reality. Constructive critism is only wanted if it can be done without much work. |