RE: Class that opens and adds variables to instances of another class?
Andy Jones <[email protected]>
| Newsgroups | gmane.comp.lang.ruby.general |
|---|---|
| Message-ID | <[email protected]> |
The way Ruby thinks of OOP borrows a lot from Smalltalk. I’m not a Smalltalk programmer, but the syntax is ridiculously easy to learn, and this book pays me back every time I read it: https://www.amazon.com/Smalltalk-Best-Practice-Patterns-Kent/dp/013476904X (Although for gods’ sake don’t pay £50 for it …) From: ruby-talk [mailto:[email protected]] On Behalf Of leam hall Sent: 19 July 2018 14:29 To: Ruby users Subject: Re: Class that opens and adds variables to instances of another class? Hah! I may need a Smalltalk primer, I keep seeing references to it. Yes, I think your last example is closer to the need and a Decorator might not be what I'm looking for. The simple explination is: al = Person.new Something_That_Changes_Character.new(al) Something_Else_That_Also_Changes_Character.new(al) In each case "al" has several attributes modified or added. The "al" passed to the second Something carries the modifications from the first. Leam On Thu, Jul 19, 2018 at 9:22 AM, Andy Jones <[email protected]<mailto:[email protected]>> wrote: Well, first, it seems as if you might find it easier to keep the classes for character creation and the actual game somewhat different. Have the game read the JSON into a separate “model” class that keeps it away from the complexities of character creation, and just lets it deal with the resulting character? I don’t know. Second, it seems to me that all your characters want to partake in all your addon functionality. The use case for Decorator Pattern is rather different. It’s popular in game design, but not usually used in that way, but rather like this: flora = Character.new(“Flora the elven druid”) flora.exend Elf flora.exend Druid varian = Character.new(“Varian the dwarven undead druid”) varian.extend Dwarf varian.extend Undead varian.extend Druid (Apologies if the formatting is odd, Outlook is playing Silly Devils) If I understand correctly, you might want to go to what Smalltalk used to call “Method Classes” – where you farm off some of your functionality to a helper class that does a job, returns a result, and then never gets called again. It seems like your CharacterCreation might best be that sort of class. But I don’t know it well enough to say for sure. class Person def initialize(name, strength) @name, @strength = name, strength @foo = ValueOfFooFigurerOuter.new(strength).go end end In the above example, the Person class doesn’t have to care how @foo is calculated. A helper class does that for it. Hope that helps… From: ruby-talk [mailto:[email protected]<mailto:[email protected]>] On Behalf Of leam hall Sent: 19 July 2018 13:57 To: Ruby users Subject: Re: Class that opens and adds variables to instances of another class? Hmm..good question. This stems from my Traveller stuff and the game I'm writing, which have two different uses for the Person class. Here's the logic: 1. Every instance of Person Has a name, gender, and UPP. (character stats) Can be stored in a language agnostic manner (using JSON) 2. CharacterCreation adds to an instance of Person Adds physical description, personality 3. Careers add to the instance of person Skills, rank, notes, money, "stuff" A character can go through multiple careers. 4. FreeTrader (the game) uses a limited subset of the Person + Additional stuff. Ship position(role), Game uses JSON Uses Careers, might use CharacterCreation. 5. CharacterData (the database) stores as much information about each character as possible. Planning to use Hanami/Sinatra? and a MongoDB backend. Used to track details of characters for games and books I'm writing. FreeTrader and CharacterData are separate projects but I want to build from the same Person base and extend from there. That's why the instance of a Person might have some attributes and not others. Leam On Thu, Jul 19, 2018 at 6:12 AM, Andy Jones <[email protected]<mailto:[email protected]>> wrote: You have to ask yourself: composition or mixin? The easiest way is with a mixin, but it has limitations. ~~~~ module Engineer def can_do_engines?; true; end end class Person def initialize(name); @name = name; end end p = Person.new("fred") p.extend Engineer puts p.can_do_engines? ~~~~ Note that you decorate an object --- not a class. If you want to add to the functionality of every instance of a class, I'm not sure that counts as Decorator pattern? If you want to do it with Composition, instead, have a look at the Ruby documentation for Forwardable. (Sorry this is a bit rushed; chaotic today...) I think that this might be the article that originally clued me into Decorator? Not sure: https://robots.thoughtbot.com/evaluating-alternative-decorator-implementations-in -----Original Message----- From: ruby-talk [mailto:[email protected]<mailto:[email protected]>] On Behalf Of Leam Hall Sent: 19 July 2018 10:59 To: Ruby users Subject: Class that opens and adds variables to instances of another class? I think I'm trying to figure out the Decorator pattern. What I want is to have a <thing> that takes an instance of <something> and changes it. The changes can include modifying and adding instance variables. Haven't quite figured it out yet, thoughts? Thanks! Leam Here's the error: ### Traceback (most recent call last): 3: from test_decorator.rb:28:in `<main>' 2: from test_decorator.rb:28:in `new' 1: from test_decorator.rb:17:in `initialize' test_decorator.rb:20:in `assign_role': undefined method `role=' for #<Person:0x0000562e9a870978 @data={:name=>"Al"}> (NoMethodError) ### Code: ### 1 class Person 2 def initialize(data) 3 @data = data 4 end 5 def name 6 @data[:name] || "Fred" 7 end 8 end 9 10 class Role 11 class Person 12 attr_accessor :role 13 end 14 15 def initialize(data) 16 @person = data[:person] 17 assign_role(data[:role]) 18 end 19 def assign_role(role) 20 @person.role = role 21 end 22 end 23 24 data = {:name => 'Al'} 25 26 al = Person.new(data) 27 role_data = {:person => al, :role => 'Cadet'} 28 Role.new(role_data) 29 puts al.name<http://al.name> 30 #al.role = "Cadet Sergeant" ### Unsubscribe: <mailto:[email protected]<mailto:[email protected]>?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk> Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer> Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data. Unsubscribe: <mailto:[email protected]<mailto:[email protected]>?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk> Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer> Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data. Unsubscribe: <mailto:[email protected]<mailto:[email protected]>?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk> Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer> Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data. Unsubscribe: <mailto:[email protected]?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>