Hi
I have the following class
CPopulation
which could contain any of the following subclasses, dependent upon the
data being held
CDateStatistics
which contains the method
Public Function Mean() as Date
CValueStatistics
which contains the method
Public Function Mean() as Double
CTextStatistics
which contains the method
Public Function Mean() as Text
It also, at present, declares a member variable as an interface class
IStatistics
which declares the method
Public Function Mean as Variant
which would be implemented by all the CxxxxStatistics classes
I want to expose the Statistics classes from the CPopulation object.
Dim myPopulation as CPopulation
myPopulation.AddData ...
debug.print myPopulation.Mean
and then delegate down to the subobject.
I'm wondering though
a) is there another way of structuring/designing this so that I don't
have to use a variant. (For example I could expose CDateStatistics,
CTextStatistics, CValueStatistics as properties, directly but dependent
upon what data is being analyses, 2 of these will be redundant and the
object's consumer could potentially make inappropriate calls i.e. call
the TextStatistics.Mean for a population of value data. Yet this does
have advantages in that there may be certain analyses which are
inappropriate for certain types of data)
or
b) perhaps it is not really a problem?
For example, if in implementing the IStatistics interface in the
CValueStatistics class I delegate thus
Private Function IStatistics_Mean() as Variant
IStatistics_Mean = Mean
End Function
Public Function Mean() as Double
... calculate average
End Function
is there any casting going on to convert the double to a variant or is
the variant simply wrapping the double in some way.
Thx in advance
Simon
Larry Serflaten - 28 Dec 2007 13:09 GMT
> I have the following class
> CPopulation
[quoted text clipped - 4 lines]
> CValueStatistics
> CTextStatistics
> It also, at present, declares a member variable as an interface class
>
[quoted text clipped - 13 lines]
>
> and then delegate down to the subobject.
Obviously, I don't have all the information of what you are trying to do,
but at first glance, I had to wonder why you had 3 different classes
similarly named, with a common function. I would have thought you
might have used CDate, CText and CValue classes that all implement
an IStatistics interface.
Then on the cPopulation object you'd have a Statistics object that
has three objects: Dates, Texts, and Values that all return the IStatistics
type, such that your calling convention would look more like:
X = CPopulation.Statistics.Dates.Mean
Y = CPopulation.Statistics.Texts.Mean
Z = CPopulation.Statistics.Values.Mean
But to answer your question, as far as I know you only have two
choices, you can either define your interface using a Variant and let
VB handle the coersions where needed, or you could use a String
and allow the user to either force the conversions or let VB do it.
Since Date to String formating can vary from machine to machine
as well as locale to locale, I would probably pick the Variant route
and let VB manage the necessary conversions to or from the Variant.
LFS
Simon Woods - 28 Dec 2007 14:06 GMT
>> I have the following class
>> CPopulation
[quoted text clipped - 47 lines]
>
> LFS
Thanks Larry this gives me some food for thought ...
Your naming is much better as is your architecture!
Ralph - 29 Dec 2007 19:04 GMT
> Hi
<snipped>
While you're still chewing on it, consider this...
When you start marking out classes and sub-classes (that will define
objects) you are using generalization or inheritance to describe an "IS A"
relationship. Based on what I gleamed, you have the following 'thingys'...
CDateThingys - is a bag of dates
CValueThingys - is a bag of doubles
CTextThingys - is a bag of Text thingys
These bags had rules and descriptors (attributes) associated with them so
you went the next step and abstracted the rules as a unique collection type
called a Population. There is where your additional object came in.
"Statistics" - since statistics decribes the rules and attributes a
Population may have. But - Can you say "a Population IS A Statistic"? Nope.
A Population "USES" statistics. A Population "HAS A" mean.
So what you really want is a Templated Class. "CPopulation<datatype>"
unfortunately VB doesn't support templates. You can only use generalization,
and VB provides only "Parameterized Polymorphism" (Variants) or "Interface
Inheritance". You don't want the former - you are stuck with the latter. So
you might migrate to something like this ...
CPopulation
Implements IDates
Implements IValue
Implements IText
And use it like this...
Dim MyBag As IDates: Set MyBag = New CPopulation
MyBag.Add dt
...
vMean = MyBag.Mean()
...
MyBag.Save
Very clean and simple, but that gets mechanically awkward with VB.
CPopulation will get huge, especially when you consider all the separate
code for creating the bags and validating content. From a practical point of
view, with a limited number of datatypes, this might serve you better...
CBagOfDates
Implements IPopulation
CBagOfValues
Implements IPopulation
CBagOfText
Implements IPopulation
Using it like this...
Dim MyBag As CBagOfDates: Set MyBag = New CBagOfDates
MyBag.Add dt
...
Dim DatePopulation As IPopulation
Set DatePopulation = MyBag
vMean = DatePopulation.Mean()
...
MyBag.Save
This means a unique class for each DataType and a separate reference every
time you want to treat it like a "population". A PITA and mildly ugly but
perhaps less awkward when it comes to managing specific datatype nuances
within one file.
Twiddledee, Twiddledum. <g>
-ralph
Steve Gerrard - 29 Dec 2007 22:44 GMT
> I have the following class
> CPopulation
[quoted text clipped - 3 lines]
> CValueStatistics
> CTextStatistics
> is there any casting going on to convert the double to a variant or is
> the variant simply wrapping the double in some way.
It's a slow Saturday, so here are some thoughts.
1. When you return a double as a Variant, a new Variant is created, its type is
set to Double, and the value of your double is copied into it.
2. What is the meaning of the mean date, and even odder, the mean string value?
Just curious...
3. An interface method which returns a Variant that might be a Double, a Date,
or a String strikes me as a pain in the neck. That means I get to write code to
check the data type every time, before I can do anything with it. To me, the
point of an interface is to allow me to write code which is independent of the
type of the actual objects being processed.
4. It's not clear to me if instances of CPopulation will always contain data of
just one type, or if it will be a mixture of the three. If it is a mixture, I
don't what the Mean would signify. If it is all one type, why not just have a
CValuePopulation and a CTextPopulation? I don't see the benefit of a interface
or single class if the data types are so different from each other. How much
code can they really share?
5. Which leads to the question, what are you really after here?