I want to be able to perform "math" operations on object instances.
lets assume I have a Fruit
class and then additional Orange(Fruit)
and Apple(Fruit)
classes.
Apple
's have a color attribute and the class is aware of the face that "red apples" are different then "green" or "yellow" Apples.
now I want to be able to:
1) represent quantities of a specific fruit instance. e.g. 3 red Apples or 2 Oranges or 1 Banana (Yep, that would probably require a new Banana class).
2) represent "Fruit bags". e.g. 1 red Apple and 2 Oranges. or 1 red Apple and 2 Oranges
3) operate on "Fruit bags" and "Fruit quantities" as would be expected. i.e. "2 red Apples" + "1 red Apple and 1 Orange" => "3 red Apples and 1 Orange" and maybe even "2 red apples" * 2 => "4 red apples" and so on.
now,
In some aspects it looks similar to what that Counter
class does, but I am not sure how I should go about implementing this.
My basic dilemma here is that it would seem that the Counter
class determines if two objects are the same based on their hash and does the grouping based on this same hash and does not provide an option for me to decide that the key to group "3 red Apples" is "red apple".
I know how to handle all the math overloading issues and I guess I can implement it all from the ground up, but I was hoping that there is some other ready made solution that would support those concepts.
The real application is of course more complicated but I think that a solution to the problem as i described here would be easy to extend to my actual requirements.
What approach would you suggest that I take on this? can Counter be used some how or do I need to do my own full implementation?
EDIT 1: some more thoughts I really like the comment by @jbndlr about "You say integer w/ value 3, not 3 integers". But there there is a difference...
How would you count together an integer w/ value 1, an integer w/ value 1 and a third integer w/ value 4? would three integers be the right answer? or maybe "2 integers integers w/ value 1 and 1 integer w/ value 4 ?
Counting is not like summing...
From some abstract level it would make send to count things based on their type, and which would force you to do a strong distinction between '1 red_apple' and '1 apple which is red' in the sense that '1 red_apple' + '1 green_apple' are just '1 red_apple + 1 green_apple' (because a green_apple is different then a red_apple) while '1 apple which is red' + '1 apple which is green' can be though of as '2 apples' (because an apple by any other color would be as appleish)
The issue is that if your application domain requires that you group apples by color you still don't want to be forces to create 3 different classes of apples, you just want to distinct apple instances by color.
It would be that I am going the wrong way about this and that the right way to decide how to count would be by the one doing the actual counting so that the you could provide the hashing scheme as part of the call to some CounterFactory function that would the return a Counter that knows what is expected of him with respect to any provided instance of object of some type.
the other alternative is to assume that each type is only countable in some specific way and it is up to the class to know what is the right way to count its instances and so provide something like a __counting_key__ to support a backwards compatible way to control the behavior of the Counter class.
Thanks for all the great answers, I certainly got enough to be able to work with. I will accept the one that would seem closest to the solution I will actually choose eventually.
This is Jon Clements answer posted on a Gist here:
I am posting his answer as a community wiki answer.