|
I am not sure if I am not understanding the use of interfaces or just going about this the wrong way. Any help would be appreciated. Here is the gist of what I am trying to do:
I have a class - Dog - which implements a few basic methods such as tail-wagging and slipper chewing:
class Dog {<br />
void wagTail(){...};<br />
void chewSlippers(){...};<br />
}
Now I wish to create a bunch of types of dogs, so:
class doberman : Dog {...)<br />
class labrador : Dog {...}<br />
class chihuaha : Dog {...}<br />
etc.
So far so good. Dobermans, labs and chihuahas can all wag their tails and chew slippers. But I also want dogs to be able to do a trick, so I thought I would force the programmer to create the doTrick method by making it an interface:
interface IDog {<br />
void doTrick();<br />
}
Here is my problem. The programmer is going to deal with the instances of dogs as part of a collection, so he is not necessarily going to know if the object being used is a doberman or a labrador or what. e.g. the code may look like:
foreach ( Dog myDog in AllDogsInMyHouse ) {...};
If I implement the interface on the individual classes
class doberman : Dog, IDog {...)<br />
class labrador : Dog, IDog {...}<br />
class chihuaha : Dog, IDog {...}<br />
etc.
the programmer must create the doTrick() method for each one - great. But the programmer isn't able to call myDog.doTrick() because doTrick is not defined for the class myDog.
If, instead, I implement the interface on the class myDog
class Dog : IDog {<br />
void wagTail(){...};<br />
void chewSlippers(){...};<br />
void doTrick(){...};<br />
}
the programmer can call myDog.doTrick(), but I now have to provide a default method for doTrick() which is automatically inherited by doberman, labrador, etc. This defeats the purpose - the programmer is not forced to create a doTrick() himself.
Is there a way for me to accomplish both goals?
Clive Pottinger
Victoria, BC
|
|
|
|
|
Make the class Dog abstract, so you will have the following:
abstract class Dog : IDog {
void wagTail() { ... }
void chewSlippers() { ... }
abstract void doTrick();
} Hope this helps,
Sounds like somebody's got a case of the Mondays
-Jeff
|
|
|
|
|
Many thanks. That worked.
I had read about abstract, but it didn't quite make sense to me until now.
Clive Pottinger
Victoria, BC
|
|
|
|
|
What Jeff said is the right way to do it; the Dog class should be abstract, and there should be an abstract method called DoTrick on it.
Another way of doing this, if you wanted to keep the Dog class non-abstract, you could do it like this:
class Dog
{
public virtual void DoTrick()
{
}
} Notice the virtual method - that means derived classes, such as Dobermans, can override that method and provide their own implementation:
public class Doberman
{
public override void DoTrick()
{
...
}
} This will accomplish the same thing: all dogs can do a trick. However, it doesn't force derivatives to implement DoTrick; if Doberman didn't override it, DoTrick would exist but would do nothing (e.g. see the Dog.DoTrick method). If you want to force derivatives to provide a custom DoTrick method, an abstract method is the way to go, just like Jeff showed you.
|
|
|
|
|
While the above answers are correct, I'm going to throw a one into the pot that you might not be aware of. You can use Partial Methods to accomplish a similar thing in .NET 3.5. Basically it allows you to put a call to a partial method and call it from your code. If the method is present, in the implementation then it will be called otherwise it will be compiled out. Take a look at this[^] site for more information.
|
|
|
|
|
I'm drawing a Splash Screen (Custom Shaped WinForm) as follows
class SplashScreen : Form
{
Image splashImage;
public SplashScreen()
{
this.TopMost = true;
this.ShowInTaskbar = false;
this.FormBorderStyle = FormBorderStyle.None;
this.StartPosition = FormStartPosition.CenterScreen;
this.BackColor = this.TransparencyKey = Color.White;
this.BackgroundImage = splashImage = Bitmap.FromFile(SplashFileName);
this.Size = this.BackgroundImage.Size;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawImage(this.splashImage, 0, 0, this.Width, this.Height);
}
}
and showing it in my Main method as
class MainForm : Form
{
public static void Main(String[] args)
{
SplashScreen splash = new SplashScreen();
splash.Show();
MainForm mainForm = new MainForm();
mainForm.Shown += delegate(object o, EventArgs ev)
{
splash.Hide();
splash.Dispose();
mainForm.Activate();
mainForm.Focus();
};
mainForm.Show();
Application.Run(mainForm);
}
}
Now the Issue is that the Splash Screen shows fine as per the Image from "SplashFileName" but just before showing it shows a Black Rectangle for some milliseconds. What I expect is that the Splash Screen be shown while my program is loading stuff and hide as soon as the MainForm gets Shown. So Where am I missing?
Please Advice
Thanks...
|
|
|
|
|
Hi,
as the splash image seems intended to fill the splash form, I see no reason to call base.OnPaint()
so I suggest you take it out.
|
|
|
|
|
protected override void OnPaint(PaintEventArgs e)<br />
{<br />
base.OnPaint(e);<br />
e.Graphics.DrawImage(this.splashImage, 0, 0, this.Width, this.Height);<br />
}<br />
I tried removing base.OnPaint(e) from above and removed the above method completly but still a get a Black Rectangle of the same Dimensions as my Splash Screen before I the latter becomes visible
|
|
|
|
|
Hi,
I did some experiments, and it clearly is this.TransparencyKey = Color.White;
that causes the initially black window. If you remove it, everything looks fine; if you need
transparency, there might not be a solution (except maybe switching to WPF).
|
|
|
|
|
Thanks for the reply. Yes taking out this.TransparencyKey = Color.White; does get rid of the Black Rectangle but my Image is not Rectangular. I know that we can draw Non-Rectangular WinForms using
this.BackColor = this.TransparencyKey = SomeColor; //Color.White in my case
In case you want to investigate further then my SplashForm Image is located at
SplashScreen Image[^]
|
|
|
|
|
Ok, I have a set of graphics paths that are drawn to a Panel on a Form. This Panel will at times expand and require scrolling to see more of the area. However, when redrawing the Graphics paths or using hit detection, the Graphics paths don't seem to be operate within the panel's client area, rather, operating on the panel as if there were no scrolling.
What suggestions would you recommend to alleviate this problem?
|
|
|
|
|
Do you have this working yet?
"Real programmers just throw a bunch of 1s and 0s at the computer to see what sticks" - Pete O'Hanlon
|
|
|
|
|
hi all!
i want to learn about Cell phones (mobile telephones) application using c#.net.some mobile support some language in any case I'm beginner for this .is there any tutorial about Cell phones (mobile telephones) application using c#.net(for e.g. transfer files to mobile and , creating menu for some special language and ...).
thanx in advance!
yours,
s_mostafa_h
|
|
|
|
|
Get it
SSK.
Anyone who says sunshine brings happiness has never danced in the rain.
|
|
|
|
|
thx for ur reply,
but my means is , I want to make a tools application that i can transfer or erase file from cell phone by this application for example . or if any file on this device destroyed or ... i can add some flash files to this device ....by this application .
thx in advance
s_mostafa_h
|
|
|
|
|
Im writing a application on vs2003 taht has to create a new event log just like application event log
the only problem is that i cant set the size of the event log and make it overrite as needed
1. how can i do that?
2. if i wantr to copy this event log file how do ido that?
sample code will be greate help
thanks
|
|
|
|
|
Hi all
I have a framework that define few interfaces. The types implementing those interfaces are not known before runtime, and are instantiated using the System.Type class and the System.Reflection namespace.
I want to have your take on the best way to do this:
- Instantiating the class (using a default constructor).
- Verifying the type is an instantiable reference type (currently I use Type.IsClass and Type.IsAbstract properties).
- and, finally, the most tricky part, verifying that a particular interface is implemented by the type. Currently, I use:
if (!(typeinstance is IMyInterface)) { throw new Exception(); }
Would you recommend a different approach? I ask this because I would like to standardize a way that multiple projects could use a framework where you pass a type definition string and an interface type that this type has to implement. The method would return an instance of the interface or throw an exception if the type cannot be instantiated using Type.GetType(string, bool) for instance, is not instantiable (abstract class, for instance), or does not implement the interface.
Thank you.
-----
You seem eager to impose your preference of preventing others from imposing their preferences on others. -- Red Stateler, Master of Circular Reasoning and other fallacies
If atheism is a religion, then not collecting stamps is a hobby. -- Unknown
God is the only being who, to rule, does not need to exist. -- Charles Baudelaire
|
|
|
|
|
It's difficult to answer this question. In many applications this would be considered an exceptional situation meaning that throwing an InvalidCastException would be a valid way to design the system.
In another application the factory might be required to catch the exception internally, log the exception, and return a default implementation of the interface.
It is not really possible for us to know what your scenario needs as a solution.
|
|
|
|
|
Hi
there are at least 2 ways of doing this
1) with a generic Method that looks something like this:
public T loadObject<t>(Type TypeToLoad)
{
T RetVal = (T)TypeToLoad.GetConstructor(null).Invoke(null);
return RetVal;
}
</t>
this will throw an CastException if the Type does not the interface T
and the call is quite simple:
myInterface Obj = loadObject<myinterface>(typeof(SomeType));<br />
<br />
2) with reflection<br />
<br />
<pre><br />
public object loadObject(Type TypeToLoad, Type Interface)<br />
{<br />
Type[] ifs = TypeToLoad.GetInterfaces();<br />
if (Array.IndexOf(ifs, Interface) == -1)<br />
{<br />
throw new Exception("It didn't work!");<br />
}<br />
return TypeToLoad.GetConstructor(null).Invoke(null);<br />
}<br />
</pre><br />
<br />
this will work with 1.1 (if you still use that one..) and it will fail *before* the instance is created. but you will have to cast the return - value to your interface type:<br />
<code>myInterface Obj = loadObject(typeof(SomeType), typeof(myInterface)) as myInterface;
greets
m@u
|
|
|
|
|
Thanks for you reply. 1) will not work, generics are good for early (compile-time) bindings. In my case, this is late (runtime) binding.
-----
You seem eager to impose your preference of preventing others from imposing their preferences on others. -- Red Stateler, Master of Circular Reasoning and other fallacies
If atheism is a religion, then not collecting stamps is a hobby. -- Unknown
God is the only being who, to rule, does not need to exist. -- Charles Baudelaire
|
|
|
|
|
Hi,
How do I reduce this code and make it simpler please?
As you can see these are the lines repeated in both conditions
newForm.ReportNameGet(strReportName.ToLower().ToString());
newForm.SecurityID = intSecurityID;// Provide the SecurityID to the new form.
newForm.ShowDialog();// Show the form.
newForm.Dispose();
I would like to move these above lines to the end of the code and so make the procedure simpler.
I thinkk this can be done by declaring the form before the if statement? if so, can you let me know how?
if (strReportName == PRICEHISTORY)
{
frmHistoryDetails newForm = new frmHistoryDetails();
newForm.ReportNameGet(strReportName.ToLower().ToString());
newForm.SecurityID = intSecurityID;// Provide the SecurityID to the new form.
newForm.ShowDialog();// Show the form.
newForm.Dispose();
}
else if (strReportName == PRICEHISTORYBEST)
{
frmHistory newForm = new frmHistory();
newForm.ReportNameGet(strReportName.ToLower().ToString());
newForm.SecurityID = intSecurityID;// Provide the SecurityID to the new form.
newForm.ShowDialog();// Show the form.
newForm.Dispose();
}
|
|
|
|
|
Put the code in a method and call it every time you need it.
Kristian Sixhoej
"Failure is not an option" - Gene Kranz
|
|
|
|
|
How do I change the code so that the following works please?
I ask because this is what I would like to have but newForm gives an error on line indicated by ????
if (strReportName == PRICEHISTORY)
{
frmHistoryDetails newForm = new frmHistoryDetails();
}
else if (strReportName == PRICEHISTORYBEST)
{
frmHistory newForm = new frmHistory();
}
?????
newForm.ReportNameGet(strReportName.ToLower().ToString());
newForm.SecurityID = intSecurityID;// Provide the SecurityID to the new form.
newForm.ShowDialog();// Show the form.
newForm.Dispose();
|
|
|
|
|
What exactly is the error?
Kristian Sixhoej
"Failure is not an option" - Gene Kranz
|
|
|
|
|
What error it says?
SSK.
Anyone who says sunshine brings happiness has never danced in the rain.
|
|
|
|