Hey, all:
I figure this is a beginner question. I get a big warning when I override certain methods. (Class methods?) For example, if I want to set up the "contractless" part of my object, I do so by overriding #basicNew, and then setting the values that allow the instance of the object to function. This seems perfectly normal and reasonable, but I get this big warning about how terrible it might be. I not even 100% clear on how it could be so terrible beyond that particular class. (I guess it's possible in this way to create an object that destabilizes the system?) Am I doing this wrong/non-optimally? (Maybe I should be overriding #new instead of #basicNew, but I get the same dire warning for #new). ===Blake=== P.S. Seeing if this goes through; last message I sent warned me that I wasn't on the mailing list. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Hi Blake, You should *never* *never* *never* override #basicNew! If fact, never override any #basic* methods. If you override them, then you can't get at them anymore. At some point you must actually create a new object, and the only way you can do this (well, the only reasonable way) is to eventually send #basicNew. Of course #new does this for you, so if you override #new, or provide another way of creating instances, then that's where you will send #basicNew. Maybe if you describe your problem, it would be easier to suggest a reasonable way of doing it. - on On Jan 20, 2008, at 10:45, Blake wrote: > Hey, all: > > I figure this is a beginner question. > > I get a big warning when I override certain methods. (Class methods?) > > For example, if I want to set up the "contractless" part of my > object, I do so by overriding #basicNew, and then setting the values > that allow the instance of the object to function. This seems > perfectly normal and reasonable, but I get this big warning about > how terrible it might be. > > I not even 100% clear on how it could be so terrible beyond that > particular class. (I guess it's possible in this way to create an > object that destabilizes the system?) > > Am I doing this wrong/non-optimally? (Maybe I should be overriding > #new instead of #basicNew, but I get the same dire warning for #new). > > ===Blake=== > > P.S. Seeing if this goes through; last message I sent warned me that > I wasn't on the mailing list. > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Blake-5
Hi Blake!
I've yet to find a situation where I can't put the code that would be in a constructor in C++ into #initialize. I suppose there are situations where that would be a bad idea, but I just haven't met them, or else I'm doing bad things (very likely). Every time I get that kind of a warning I treat it as a 'is there a better way?' flag. It'd be great if one of the non-newbies on this list could explain when (or why) it is a better idea to override #new rather than instantiate fields in #initialize or via lazy initialization. yours in confusion, John. > Hey, all: > > I figure this is a beginner question. > > I get a big warning when I override certain methods. (Class methods?) > > For example, if I want to set up the "contractless" part of my object, I > do so by overriding #basicNew, and then setting the values that allow the > instance of the object to function. This seems perfectly normal and > reasonable, but I get this big warning about how terrible it might be. > > I not even 100% clear on how it could be so terrible beyond that > particular class. (I guess it's possible in this way to create an object > that destabilizes the system?) > > Am I doing this wrong/non-optimally? (Maybe I should be overriding #new > instead of #basicNew, but I get the same dire warning for #new). > > ===Blake=== > > P.S. Seeing if this goes through; last message I sent warned me that I > wasn't on the mailing list. > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners > _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Blake-5
On Jan 20, 2008, at 4:45 , Blake wrote:
> For example, if I want to set up the "contractless" part of my > object, I do so by overriding #basicNew, and then setting the > values that allow the instance of the object to function. Isn't that what #initialize is for? > Maybe I should be overriding #new instead of #basicNew, but I get > the same dire warning for #new). There should be no warning for #new. It's perfectly fine to override it. - Bert - _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Blake-5
Hi Blake,
There are a number of ways to initialize an object. Overridding #new is an acceptable practice but normally this is done because you do not want a new object created. For example if you wanted to have only one instance of an object you might override #new to lookup your instance and return that instead. Sometimes calling #new on class is a bad idea, either this class shouldn't have instances, or there are other instance creation methods that should be called instead. (We usually don't override new because of other instance creation methods but I can understand the argument if someone did) For example FishTank class>>new "new should not be called please use instance creations methods instead" self error: 'Please use instance creation methods and not #new" FishTank class>>newForGallons: numberOfGallons "Create a fishTank that holds numberOfGallons" aTank := super new. "call super to bypass error" aTank numberOfGallons: numberOfGallons. aTank calculateGlassForGallons. aTank calculateTopSizeForGallons. aTank calculateNumberOfLightsForGallons. ^aTank Ok so this is kinda silly but I hope you get the idea. This is what happens when I make stuff up on the spot! Ok so in most cases you can set your object up in #initalize FishTank>>initialize "set up default values for aFishTank" self glassSides: OrderedCollection new. self numberOfLights: 0 copy. self tankShape: #rectangle but you might want to change that setup during instance creation. Let's move our setup code to the instance side. FishTank>>calculateTankProperties "use the information provided to create a tank" self calculateGlassForGallons. self calculateTopSizeForGallons. self calculateNumberOfLightsForGallons. Now change your original code to this: FishTank class>>newForGallons: numberOfGallons "Create a fishTank that holds numberOfGallons" aTank := super new. "call super to bypass error" aTank numberOfGallons: numberOfGallons. aTank calculateTankProperties. ^aTank So that you can call FishTank class>>newOctagonalTankForGallons: numberOfGallons "Create an Octagonal tank that holds numberOfGallons" aTank := super new. aTank shape: #octagon. aTank numberOfGallons: numberOfGallons. aTank calculateTankProperties. ^aTank. Ok so now your code that figures out the number of sides and amount of glass to use can reference shape and figure things out. Of course I would not use hardcoded shapes in my code instead on the class side I would create a protocol called Constants Then I'd create a method called in Constants FishTank class>>octagonalShape "return a symbol that represents an eight sided fishtank" ^#octagon Then I'd call aTank shape: self octagonalShape. Instead. You could also extend your class hierarchy to support different tanks. FishTank subclass: RectangleFishTank and FishTank subclass: OctagonalFishTank Now you can use your instance creation method to find out what instance to create. This makes things much easier because now your code for calculating number of sides and amount of glass can just be written in each class and all your self shape = self class octagonalShape ifTrue ... code goes away. RectangleFishTank class>>shape "return the shape of this subclass fishtank" ^self rectangleShape OctagonalFishTank class>>shape "return the shape of this subclass fishtank" ^self octagonalShape FishTank class>>newForShape: aShape numberOfGallons: aNumberOfGallons "return a new instance of a subclass matching aShape that holds aNumberOfGallons" aClass := self allSubclasses detect: [:aClass | aClass shape = aShape] ifNone: [NotAFishTankShapeThatWeSupportException signal]. ^aClass newForGallons: aNumberOfGallons. And you can simplify your initialize with FishTank>>initialize "set up default values for aFishTank" self glassSides: OrderedCollection new. self numberOfLights: 0 copy. self tankShape: self class shape. Ok so back to someone else point. What are you trying to do? Hope this helps some. Try not to override #basicNew, and only override new if there is something about creating instances you want to change. If you are trying to affect how things are created there are lots of ways to make this happen without changing new. Happy Squeaking! Ron Teitelbaum President / Principal Software Engineer US Medical Record Specialists > -----Original Message----- > From: Blake > > Hey, all: > > I figure this is a beginner question. > > I get a big warning when I override certain methods. (Class > methods?) > > For example, if I want to set up the "contractless" part of my > object, I > do so by overriding #basicNew, and then setting the values that allow the > instance of the object to function. This seems perfectly normal and > reasonable, but I get this big warning about how terrible it might be. > > I not even 100% clear on how it could be so terrible beyond that > particular class. (I guess it's possible in this way to create an object > that destabilizes the system?) > > Am I doing this wrong/non-optimally? (Maybe I should be overriding > #new > instead of #basicNew, but I get the same dire warning for #new). > > ===Blake=== > > P.S. Seeing if this goes through; last message I sent warned me that I > wasn't on the mailing list. > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Blake-5
In VW, where initialize isn't called by default, I do this all the time:
new ^ self new initialize ;) Blake wrote: > > I not even 100% clear on how it could be so terrible beyond that > particular class. (I guess it's possible in this way to create an object > that destabilizes the system?) > _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
>>>>> "Zulq" == Zulq Alam <[hidden email]> writes:
Zulq> In VW, where initialize isn't called by default, I do this all the time: Zulq> new Zulq> ^ self new initialize You mean "basicNew", unless you like infinite loops. :) -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training! _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
> Zulq> In VW, where initialize isn't called by default, I do this all the time:
> Zulq> new > Zulq> ^ self new initialize > > You mean "basicNew", unless you like infinite loops. :) No infinite loops, but bad enough: you call #initialize twice for every new object. Lukas -- Lukas Renggli http://www.lukas-renggli.ch _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
I think he meant in VW:
new ^super new initialize On Jan 20, 2008 11:46 AM, Lukas Renggli <[hidden email]> wrote: > > Zulq> In VW, where initialize isn't called by default, I do this all the time: > > Zulq> new > > Zulq> ^ self new initialize > > > > You mean "basicNew", unless you like infinite loops. :) > > No infinite loops, but bad enough: you call #initialize twice for > every new object. > > Lukas > > -- > Lukas Renggli > http://www.lukas-renggli.ch > > _______________________________________________ > Beginners mailing list > [hidden email] > http://lists.squeakfoundation.org/mailman/listinfo/beginners > Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by John Foster-3
On Sun, 20 Jan 2008 04:37:17 -0800, <[hidden email]> wrote:
> Hi Blake! > > I've yet to find a situation where I can't put the code that would be in > a constructor in C++ into #initialize. I suppose there are situations > where that would be a bad idea, but I just haven't met them, or else I'm > doing > bad things (very likely). In the abstract, I'd say if the class knows something the instance shouldn't. > Every time I get that kind of a warning I treat it as a 'is there a > better way?' flag. It'd be great if one of the non-newbies on this list > could > explain when (or why) it is a better idea to override #new rather than > instantiate fields in #initialize or via lazy initialization. Yeah, I think that's why the warning is there. And I understand it (sorta) for #basicNew. It just seems kind of hyper for #new. I guess it's because #new is obliged (sorta) to call #initialize, and this is not a universal Smalltalk tradition. ===Blake=== _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Bert Freudenberg
On Sun, 20 Jan 2008 07:50:57 -0800, Bert Freudenberg
<[hidden email]> wrote: > On Jan 20, 2008, at 4:45 , Blake wrote: > >> For example, if I want to set up the "contractless" part of my object, >> I do so by overriding #basicNew, and then setting the values that allow >> the instance of the object to function. > > > Isn't that what #initialize is for? > >> Maybe I should be overriding #new instead of #basicNew, but I get the >> same dire warning for #new). > > There should be no warning for #new. It's perfectly fine to override it. Thank you! _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Randal L. Schwartz
In response to "(I guess it's possible in this way to create an object
that destabilizes the system?)", I was demonstrating how one might introduce instability. I would normally send super new. Randal L. Schwartz wrote: >>>>>> "Zulq" == Zulq Alam <[hidden email]> writes: > > Zulq> In VW, where initialize isn't called by default, I do this all the time: > Zulq> new > Zulq> ^ self new initialize > > You mean "basicNew", unless you like infinite loops. :) > _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by Ron Teitelbaum
On Sun, 20 Jan 2008 07:54:47 -0800, Ron Teitelbaum <[hidden email]>
wrote: > Hi Blake, > > There are a number of ways to initialize an object. Overridding #new is > an acceptable practice but normally this is done because you do not want > a new object created. For example if you wanted to have only one > instance of an object you might override #new to lookup your instance > and return that > instead. Sure, for singletons. Good example. > Sometimes calling #new on class is a bad idea, either this class > shouldn't have instances, or there are other instance creation methods > that should be called instead. (We usually don't override new because > of other instance > creation methods but I can understand the argument if someone did) Right. And while that's not necessarily ideal, I think it can be construed as part of the price of knowing how to use an object. (Though I like "contract-less" programming, do the degree it's possible.) > FishTank class>>newForGallons: numberOfGallons > "Create a fishTank that holds numberOfGallons" > aTank := super new. "call super to bypass error" > aTank numberOfGallons: numberOfGallons. > aTank calculateGlassForGallons. > aTank calculateTopSizeForGallons. > aTank calculateNumberOfLightsForGallons. > ^aTank > > Ok so this is kinda silly but I hope you get the idea. This is what > happens when I make stuff up on the spot! Well, no, this is precisely the sort of situation I run into all the time. "Gee, mister, I'd love to create an instance for ya, but I need to know what kind of instance you want." > Ok so in most cases you can set your object up in #initalize > > FishTank>>initialize > "set up default values for aFishTank" > self glassSides: OrderedCollection new. > self numberOfLights: 0 copy. > self tankShape: #rectangle > > but you might want to change that setup during instance creation. This also doens't solve your number of gallons issue. Which puts you in the position of changing that number of gallons after the instance is created. > You could also extend your class hierarchy to support different tanks. Yes. This something that I'm getting used to. Thanks, Ron. _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Free forum by Nabble | Edit this page |