Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / General / December 2007



Tip: Looking for answers? Try searching our database.

Strongly typing Subobject properties

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Simon Woods - 28 Dec 2007 10:32 GMT
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?
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.