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>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.