Peter Duniho wrote:
On Mon, 21 Apr 2008 18:10:22 -0700, John B <jb******@yahoo.comwrote:
>Whilst I agree to a point that it's _almost_ always a mistake to hide
a member.
A common pattern I use is with generics.
Say I have:
abstract class Fu
{
public virtual object Value
{
get { return ValueInternal; }
}
protected abstract object ValueInternal{get;}
}
class Bar<T: Fu
{
public new T Value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override object ValueInternal
{
get { return Value; }
}
}
This obviously allows both strong typed functionality with generics
and easy polymorphism with the base non-generic class.
Well, I'd say that once you allow the polymorphism with the base
non-generic class, you've lost the main advantage of using generics.
That is, you no longer have compile-time type checking for instances of
that class. Why bother with a derived generic in that case?
In one place I have used this pattern is where I have a base class I use
for reporting criteria.
I have a form that can add/edit/remove criteria and only knows about the
base class.
I use this base form for many report types and only the list of
available criteria changes.
One of the generic parameters (there are 2) denotes the "Field" which is
being targeted by the criteria (ie customer surname) which is redefined
in the generic class from object to <Fand in the "real" concrete class
to an enum type and returns the actual enum item the criteria is targetting.
In the concrete report forms, the criteria are then treated as their
"real" types.
An example is below my signature.
Its kind of hard to explain without an example but the "example" is not
easily extracted out of the whole application.
I also don't understand the point of making the base property virtual,
if you're just going to hide it anyway. Who's going to override it?
True, just habit of making all members virtual in abstract classes
(unless specifically necessary not to).
If one _is_ going that route, I'd say you might as well just use a
different name for the typed (generic) form of the property. Like
"TypedValue" or something like that. You'll still want to override the
base Value property, but then at least there'd be a point to having the
base class property be "virtual" and the code wouldn't seem so
circular. :)
Fair comment, I'm not really a fan though of this though, as I would
automatically type instance.Value which would then bite me as I'd get a
compile error saying ...object cant be converted to X and i'd have to
change it to instance.TypedValue so I'd have to remember to always use
TypedValue.
Obviously I won't go so far as to say hiding a member is _never_ the
right thing to do, but I don't agree that your example is proof of
that. :) It's my opinion that there are better ways to approach a
situation like that.
Quite possible that there are better ways than this. Unfortunately I'm
the only input on this so that limits me to my own ideas :)
JB
enum CustomerFields
{
Surname = 1,
FirstName,
Postcode,
}
abstract class Criteria
{
public object Field { get { return FieldInternal; } }
protected abstract object FieldInternal { get; }
public object Value { get { return ValueInternal; } }
protected abstract object ValueInternal { get; }
}
abstract class Criteria<F: Criteria
{
public abstract new F Field { get; }
protected override object FieldInternal
{
get { return Field; }
}
}
abstract class Criteria<F, V: Criteria<F>
{
V m_Value;
public new V Value
{
get { return m_Value; }
set { m_Value = value; }
}
protected override object ValueInternal
{
get { return Value; }
}
}
class CustomerSurnameCriteria : Criteria<CustomerFields, string>
{
public override CustomerFields Field
{
get { return CustomerFields.Surname; }
}
}