From: Steve P. on 27 Jul 2010 00:36 I am attempting to put as much code inside classes as possible, to economize the code in the main body. However, how do I create a new class instance using only a method defined in a class? For instance, in the following code, I want to create a new Class Character instance named newchar by fleshing out the code in the #'d area. Is it possible? Otherwise, what is best practice? PS: I realize I can instantiate newchar=Character.new(da da da) from the body of the code but that would require the prompting code be there also. that would defeat my purpose. I hope I have given this enough thought before posting! :-) Best Regards Steve. #!/usr/bin/ruby -w class Character attr_reader :chname, :chnick, :chquote def initialize(chname,chnick) @chname=chname @chnick=chnick @chquote=String.new end def addquote(quote) @chquote=quote if quote.length > 10 end def promptedinput print "Char name: ";chname=gets.chomp print "Char Nick: ";chnick=gets.chomp print "Char Quote: ";chquote=gets.chomp # Need help here! # What code goes here to add Character class instance? # class instance name should be newchar end end puts newchar.inspect #referencing added instance. __END__ -- Posted via http://www.ruby-forum.com/.
From: Jesús Gabriel y Galán on 27 Jul 2010 02:43 On Tue, Jul 27, 2010 at 6:36 AM, Steve P. <stevepauly(a)comcast.net> wrote: > I am attempting to put as much code inside classes as possible, to > economize the code in the main body. However, how do I create a new > class instance using only a method defined in a class? > > For instance, in the following code, I want to create a new Class > Character instance named newchar by fleshing out the code in the #'d > area. Is it possible? > > Otherwise, what is best practice? > > PS: I realize I can instantiate newchar=Character.new(da da da) from the > body of the code but that would require the prompting code be there > also. that would defeat my purpose. I hope I have given this enough > thought before posting! :-) Two considerations: - I tend to separate the domain objects from the code that interacts with the outside world to gather the data to populate that domain object (user typing, DB, etc). This way you gain flexibility, being able to add ways of loading or creating the object without modifying that class - If, in any case, you want the interaction with the user in that class, I would use a class method that returns an instance. If you have other ways of creating that instance you can add new methods for each case. For example: #!/usr/bin/ruby -w class Character attr_reader :chname, :chnick, :chquote def initialize(chname,chnick) @chname=chname @chnick=chnick @chquote=String.new end def addquote(quote) @chquote=quote if quote.length > 10 end def self.from_prompted_input print "Char name: ";chname=gets.chomp print "Char Nick: ";chnick=gets.chomp print "Char Quote: ";chquote=gets.chomp Character.new chname, chnick,chquote end end puts Character.from_prompted_input.inspect What you had in mind couldn't work, because your method was an instance method, so from the outside you still needed someone to call Character.new(x,y,z).promptedinput. Having class methods to instantiate objects of the class in different ways is a pretty typical idiom, check for example the Date class in core: http://ruby-doc.org/core/classes/Date.html The methods civil, commercial, etc are class methods that return an instance, constructed in a different way. Jesus.
From: Steve P. on 30 Jul 2010 20:06 Jesús Gabriel y Galán, I was able to accomplish (at least crudely) moving code from the main body to the class. I felt this was worth doing because I want as much logic as possible in the class. (Is this a worthy thing??) As you advised, I was able to create my new instance using a method that returned an object. Could you please take a look at how I implemented these two methods? Account.setupaccount, Account.report Is this how you would have structured it? Any tips or comments greatly appreciated. Steve. #!/usr/bin/ruby class Account attr_reader :nbr, :name, :coa def initialize(nbr,name,coa) @nbr=nbr @name=name setcoa(coa) end def setcoa(coa) if ["income", "expense", "asset", "liability", "capital"].include?(coa) then @coa=coa else puts "Error, defaulted to expense" @coa="expense" end end def Account.setupaccount #data entry routine inside class, not in main code body. print "enter acct nbr: ";nbr=gets.chomp print "enter name: ";name=gets.chomp print "enter presen: ";coa=gets.chomp return Account.new(nbr,name,coa) end def Account.report(acct) #reporting code inside class, not in main body. puts "===Account Number Listing===" puts "Account Nbr: #{acct.nbr}" puts "Account Name: #{acct.name}" puts "Account CofA: #{acct.coa}" end end ##Start of main code body ## newacct=Account.setupaccount Account.report(newacct) ##End of Main code body ## When I clear my confusion about this, I will do something like class Ledger < Account ##code to make an array of the Account objects and add more functionality end Jesús Gabriel y Galán wrote: > On Tue, Jul 27, 2010 at 6:36 AM, Steve P. <stevepauly(a)comcast.net> > wrote: >> PS: I realize I can instantiate newchar=Character.new(da da da) from the >> body of the code but that would require the prompting code be there >> also. that would defeat my purpose. I hope I have given this enough >> thought before posting! :-) > > Two considerations: > > - I tend to separate the domain objects from the code that interacts > with the outside world to gather the data to populate that domain > object (user typing, DB, etc). This way you gain flexibility, being > able to add ways of loading or creating the object without modifying > that class > > - If, in any case, you want the interaction with the user in that > class, I would use a class method that returns an instance. If you > have other ways of creating that instance you can add new methods for > each case. For example: > > > #!/usr/bin/ruby -w > > class Character > attr_reader :chname, :chnick, :chquote > def initialize(chname,chnick) > � @chname=chname > � � @chnick=chnick > � � @chquote=String.new > end > � def addquote(quote) > � @chquote=quote if quote.length > 10 > � end > � def self.from_prompted_input > � � print "Char name: � �";chname=gets.chomp > � � print "Char Nick: � �";chnick=gets.chomp > � � print "Char Quote: � � � � �";chquote=gets.chomp > Character.new chname, chnick,chquote > end > end > > puts Character.from_prompted_input.inspect > > What you had in mind couldn't work, because your method was an > instance method, so from the outside you still needed someone to call > Character.new(x,y,z).promptedinput. > > Having class methods to instantiate objects of the class in different > ways is a pretty typical idiom, check for example the Date class in > core: > > http://ruby-doc.org/core/classes/Date.html > > The methods civil, commercial, etc are class methods that return an > instance, constructed in a different way. > > Jesus. -- Posted via http://www.ruby-forum.com/.
From: Jesús Gabriel y Galán on 31 Jul 2010 04:59 On Sat, Jul 31, 2010 at 2:06 AM, Steve P. <stevepauly(a)comcast.net> wrote: > Jesús Gabriel y Galán, > > I was able to accomplish (at least crudely) moving code from the main > body to the class. I felt this was worth doing because I want as much > logic as possible in the class. (Is this a worthy thing??) > > As you advised, I was able to create my new instance using a method that > returned an object. > > Could you please take a look at how I implemented these two methods? > Account.setupaccount, Account.report > > Is this how you would have structured it? > Any tips or comments greatly appreciated. > Steve. > > #!/usr/bin/ruby > class Account > attr_reader :nbr, :name, :coa > def initialize(nbr,name,coa) > @nbr=nbr > @name=name > setcoa(coa) > end > def setcoa(coa) > if ["income", "expense", "asset", "liability", > "capital"].include?(coa) then > @coa=coa > else > puts "Error, defaulted to expense" > @coa="expense" > end > end Maybe call this coa=, as it's a setter? def coa=(coa) .... end > def Account.setupaccount def Account.setup_account is more idiomatic. Also I usually do def self.setup_account, but that's a matter of taste, I guess. > #data entry routine inside class, not in main code body. > print "enter acct nbr: ";nbr=gets.chomp > print "enter name: ";name=gets.chomp > print "enter presen: ";coa=gets.chomp > return Account.new(nbr,name,coa) > end > def Account.report(acct) > #reporting code inside class, not in main body. > puts "===Account Number Listing===" > puts "Account Nbr: #{acct.nbr}" > puts "Account Name: #{acct.name}" > puts "Account CofA: #{acct.coa}" > end > end > ##Start of main code body ## > newacct=Account.setupaccount > Account.report(newacct) > ##End of Main code body ## As I said, I don't really like having the user interaction inside the domain class. For reporting, specially, I would create a to_s method that formats the account info, and then have the caller of that method be the one writing to stdout or to a file or whatever: def to_s s=<<EOF ===Account Number Listing=== Account Nbr: #{acct.nbr} Account Name: #{acct.name} Account CofA: #{acct.coa} EOF s end > When I clear my confusion about this, I will do something like > class Ledger < Account > ##code to make an array of the Account objects and add more > functionality > end If you want an array of Account objects, you shouldn't inherit from Account, but rather have an instance variable that holds an array of Accounts: class Ledger def initialize @accounts = [] end ... end Jesus.
From: Brian Candler on 1 Aug 2010 07:30 Steve P. wrote: > class Character > attr_reader :chname, :chnick, :chquote > def initialize(chname,chnick) > @chname=chname > @chnick=chnick > @chquote=String.new > end > def addquote(quote) > @chquote=quote if quote.length > 10 > end > def promptedinput > print "Char name: ";chname=gets.chomp > print "Char Nick: ";chnick=gets.chomp > print "Char Quote: ";chquote=gets.chomp > # Need help here! > # What code goes here to add Character class instance? > # class instance name should be newchar > end > end I think you want a class method, not an instance method, since you're creating a new object which doesn't have any relation to any existing object. class Character def initialize(chname,chnick,chquote="") @chname=chname @chnick=chnick @chquote=chquote end def self.promptedinput print "Char name: ";chname=gets.chomp print "Char Nick: ";chnick=gets.chomp print "Char Quote: ";chquote=gets.chomp new(chnam,chnick,chquote) end end newchar = Character.promptedinput puts newchar.inspect Note that I modified your initialize method to accept chquote as an optional third argument. If you don't want to do that, then:: def self.promptedinput print "Char name: ";chname=gets.chomp print "Char Nick: ";chnick=gets.chomp print "Char Quote: ";chquote=gets.chomp result = new(chname,chnick) result.chquote = chquote result end -- Posted via http://www.ruby-forum.com/.
|
Pages: 1 Prev: IO.popen exit the program when it failed Next: thanks guys |