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:ruby-talk-***@ruby-lang.org] 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 <***@jameshall.co.uk<mailto:***@jameshall.co.uk>> 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:ruby-talk-***@ruby-lang.org<mailto:ruby-talk-***@ruby-lang.org>] 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 <***@jameshall.co.uk<mailto:***@jameshall.co.uk>> 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:ruby-talk-***@ruby-lang.org<mailto:ruby-talk-***@ruby-lang.org>] 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:ruby-talk-***@ruby-lang.org<mailto:ruby-talk-***@ruby-lang.org>?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:ruby-talk-***@ruby-lang.org<mailto:ruby-talk-***@ruby-lang.org>?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:ruby-talk-***@ruby-lang.org<mailto:ruby-talk-***@ruby-lang.org>?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.