|
As I said before, you need to go back to the book and see where the author is going with this. There are often cases where you would do this when passing an object through some code that knows about Employee s but does not know about ContractEmployee s. Some common code could adjust the properties of e without needing to know what type of employee the object refers to. At some later point you could upcast e to a ContractEmployee and process as necessary.
The best things in life are not things.
|
|
|
|
|
nstk wrote: And this is ok for me, but still I do not understand why is such a declaration useful and what it actually means. If I declare
Employee e = new ContractEmployee()
and e has the properties of the Employee class, why then not write
Employee e = new Employee()
as we "normally" do? What is the difference between those two?
The first code line means you create a new instance of class ContractEmployee. This object in memory *is* a ContractEmployee. You then have a variable e which is an Employee. Since a ContractEmployee is specifically also an Employee (ContractEmployee derives from Employee) this is a valid assigment.
The difference between the two lines is that in the first, e behaves like a ContractEmployee and in the second e behaves like an Employee.
However, through e you can only access members of ContractEmployee which are also part of Employee.
The most important thing to distinguish in these examples is the difference between the actual object created (and in memory), which is specified by new, and the interface you are using to access it.
The actual object you create is different in both examples, but the interface you use to access them is the same.
To properly explain this sample, we'd need to explain almost everything about classes and inheritance, and it seems you're not there yet. So probably, it's best to keep those questions in the back of your head until you get to that subject and ask them again; probably, you'll find you know the answers
|
|
|
|
|
Nice explanation.
The best things in life are not things.
|
|
|
|
|
I thought of it, that maybe it is one of the questions that is going to be answered by itself with time. Nevertheless, thank you for your descriptive answer, it helps a lot. There is however one point regarding the following:
MicroVirus wrote: The difference between the two lines is that in the first, e behaves like a ContractEmployee and in the second e behaves like an Employee.
In that case shouldn't have been the same if we wrote:
ContractEmployee e = new ContractEmployee()
|
|
|
|
|
In short, such a declaration is useful because of polymorphism. Code which does not know about ContractEmployee can still call methods on it if they are overrides of virtual (or abstract or interface-defined) methods of a base class. For example consider the class hierarchy (another common OO tutorial one):
abstract class Animal {
public abstract string Noise { get; }
public virtual string Feed() { return "Mm, tasty."; }
}
class Dog : Animal {
public override string Noise { get { return "Woof."} }
public void GiveBone() { Console.WriteLine("Chomp."); }
}
class Cow : Animal {
public override string Noise { get { return "Moo."; } }
public override string Feed() { return "I'll only eat it if it's green."; }
}
Now, because the methods are virtual, polymorphism will ensure that the appropriate one is called when they are dispatched on an instance of Animal, and 'down-casting' to feed instances to a more generic (in the normal English sense of the word) method is appropriate:
void FeedAndListen(Animal animal){
Console.WriteLine(animal.Feed());
Console.WriteLine(animal.Noise);
}
static void Main(){
List<Animal> animals = new List<Animal>();
animals.Add(new Dog());
animals.Add(new Cow());
foreach(Animal animal in animals) FeedAndListen(animal);
}
Note how FeedAndListen produces the output from the derived methods, even though the instances are 'downcasted' into a List<Animal> and passed to it as Animal, not their actual declaration class. Also note how you can put the different subclasses into the one list. Finally, see how Dog inherits the Feed behaviour because it is not overridden. And you can't call methods which are not defined on the base class.
I agree with the other comment which says that as you complete your OO training you will naturally see how these concepts work.
|
|
|
|
|
BobJanova wrote: Code which does not know about ContractEmployee can still call methods on it if they are overrides of virtual (or abstract or interface-defined) methods of a base class.
This is also an answer that explains a lot. Thank you.
|
|
|
|
|
You have Employee instance and you assign an instance of the ContractEmployee to it. So you can do something like this (I'll take example from Wayne Gaylard):
class Employee
{
public void Talk()
{
MessageBox.Show("I am an Employee.");
}
}
class ContractEmployee: Employee
{
public void ContractTalk()
{
MessageBox.Show("I am a Contract Employee.");
}
}
Then you can do:
static void CreateEmployee()
{
Employee e = new ContractEmployee();
e.Talk();
((ContractEmployee)e).ContractTalk();
}
But you can't do:
static void CreateEmployee()
{
Employee e = new Employee();
e.Talk();
((ContractEmployee)e).ContractTalk();
}
On this example it seems useless, but it is sometimes useful. For example you can have a class structure of different user type, all inheriting from User , you can store them on in a collection of User s
Don't forget to rate answer, that helped you. It will allow other people find their answers faster.
|
|
|
|
|
Let's make a better example for this:
class Employee
{
public string Name { get; set; }
}
class ContractEmployee : Employee
{
public object Contract { get; set; }
}
class Program
{
static void Main()
{
Employee e = new ContractEmployee();
e.Name = "Ricky";
e.Contract = new object();
}
}
nstk wrote: which properties and methods does the object e has?
e object, at runtime, has the properties and methods defined within ContractEmployee class, because it is the object you have created with new, so it has Name (inherited from Employee class), and Contract (defined within ContractEmployee ). However, without any casting, from e object you will only be able to access those members defined within Employee class (Name property in this case), because it is the type you have used to declare the object. Why? Because e object is declared as Employee , and Employee does not define a member named Contract . Yes, e is a ContractEmployee instance and, yes, it has a Contract property, but the compiler does not know it. All the compiler knows is that e object is declared as Employee , so it allows you to access only the members defined in Employee class. So, if you want to access the Contract property of e object, in this case, you would need a previous casting operation:
((ContractEmployee)e).Contract = new object();
ContractEmployee ce = (ContractEmployee)e;
ce.Contract = new object();
nstk wrote: how should I read this?
Any ContractEmployee object is a Employee , always, so you can declare an Employee and instantiate a ContractEmployee , but not in the other direction, I mean, not all of the Employee objects have to be ContractEmployee .
|
|
|
|
|
The object refered to by e is a ContractEmployee and therefore contains all the trimmings of a ContractEmployee . However... because e has been declared as an Employee , it exposes only those properties and methods defined by the base class. In other words, the following test will succeed:
1 Employee e = new ContractEmployee();
2 Debug.Assert (e is Employee);
3 Debug.Assert (e is ContractEmployee());
For e to expose its ContractEmployee properties and methods, you'd need to first cast it to a ContractEmployee .
1 Employee e = new ContractEmployee();
2 ContractEmployee ce = e as ContractEmployee;
3
4 Debug.Assert (ce != null);
/ravi
|
|
|
|
|
nstk wrote: Or maybe it's the opposite that is true?
Yes. It is indeed the opposite that is true.
The sub class has access to all the protected members of the parent class but not the other way round.
Whenever we say we have a object deriving from something, we are always assuming that this object has properties of the parent and adds on some of its own.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
|
|
|
|
|
Hi,
is it possible use as argument of reused constructor something calculated in the constructor itself?
something like
Test(double b_):this(b_,c)
but where c comes from constructor itself. A simplified example:
lass Test
{
double area;
public Test(double b_)
{
double c = b_ * Math.Sqrt(44);
}
public Test(double b_ , double l)
{
area = b * l;
}
}
Thanks for your time
TheGermoz
|
|
|
|
|
Not like that, no. When you do something like:
Test(double b_):this(b_,c)
The underlying constructor (The two-arg one in this case) is executed BEFORE the current one, so it can't use variables that haven't been calculated yet.
You could use an initialization function, called from each constructor...
public Test(double b_)
{
double c_ = ...
Initialize(b_, c_);
}
public Test(double b_, double l)
{
Initialize(b_, l);
}
private void Initialize(double b_, double l)
{
...
}
|
|
|
|
|
thanks a lot very clear answer
|
|
|
|
|
Or maybe Test(double b_):this(b_,b_ * Math.Sqrt(44)) ?
|
|
|
|
|
ok but in my specific case
// here do some operation with b, to obtain c.
so to get c from d I need many lines of code...
unfortunately I can not use your good hint
Thanks a lot anyway..
|
|
|
|
|
You can put expressions in the call to the base constructor, including calls to other classes and to static methods. In your case, the expression is simple, so you can do
public Test(double b) : this(b, b * Math.Sqrt(44)) { ...
... although that number should really be a declared constant (not sure if the compiler is clever enough to work out that it's constant).
You can't call any instance methods, because none of your constructor code has run yet and so the object is not in a valid state. You should never need to do that, as the constructor parameters (which you can pass to a static method) by definition completely define the state of the new object.
Be careful doing this, as it can lead to unwieldy code quite easily. Generally, putting a lot of logic in constructors is a symptom of a higher level design problem – it should usually be moved into initialisation methods or to where it is actually needed.
|
|
|
|
|
I have the following code to draw a grid based on the size, width and height of a map:
public void DrawCollisionMap(Map map)
{
_panel.AutoScrollMinSize = new Size(map.Width*Map.TileSize, map.Height*Map.TileSize);
_panel.Paint -= _panel_Paint;
_panel.Paint += _panel_Paint;
_panel.Invalidate(true);
}
void _panel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
for (int x = 0; x < _map.Width; x++)
{
for (int y = 0; y < _map.Height; y++)
{
e.Graphics.DrawRectangle(_pen, x * Map.TileSize, y * Map.TileSize, _map.Width, _map.Height);
}
}
}
The problem is that when it is rendered the grid does not render correctly:
http://imageshack.us/photo/my-images/864/gridr.jpg/[^]
I do not understand
|
|
|
|
|
venomation wrote: I do not understand
Man, are you happy or sad now?
venomation wrote: The problem is that when it is rendered the grid does not render correctly
What do you mean? what's your expected output?
|
|
|
|
|
venomation wrote: I do not understand
I do. I read your code and saw the mistake right away.
However I'm not going to tell you what it is, I just give you some advice: when something does not behave as expected, trim it down to a fraction of what you intend to have, and check that first.
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Please use <PRE> tags for code snippets, they improve readability. CP Vanity has been updated to V2.3
|
|
|
|
|
Aha how silly of me !
Apart from being silly the other reason why I didn't notice the maps dimensions instead of the tile-size is that I got it working on DirectX so "thought" I knew what I was doing ^^.
Thanks for making me see the light
|
|
|
|
|
We're not done yet. I have two comments on your code:
1.
the remove-then-add-a-handler stuff looks unnecessary. Why are you doing this?
2.
once you fixed the error, you are drawing a large number of tiny adjacent rectangles, which means a lot of computational effort, and also each tiny edge gets drawn twice. And all you really need for a grid of N by N cells, is N+1 horizontal lines and N+1 vertical lines. That does not take more code, it does not have nested for loops, and even may be less error prone!
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Please use <PRE> tags for code snippets, they improve readability. CP Vanity has been updated to V2.3
|
|
|
|
|
The event handling is terrible I know, only there for a quick hack as I wanted to fix the old issue...
The cells need to be "cell by cell" instead of lines as the user will change them (tile map style).
I don't know if your suggestion would help for that, I made a slight improvement in the loop by calculating the difference before:
for (int x = dbPanel1.HorizontalScroll.Value%size; x < width*size; x+= size)
{
for (int y = dbPanel1.VerticalScroll.Value % size; y < height * size; y += size)
{
e.Graphics.DrawRectangle(_p, x , y , size, size);
}
}
|
|
|
|
|
Yes, the readability has increased a lot.
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Please use <PRE> tags for code snippets, they improve readability. CP Vanity has been updated to V2.3
|
|
|
|
|
Some more comments, out of the blue:
1. if you create instances of a class that has a Dispose() method(such as Graphics, Font, Pen, Brush), you should call it when done with the objects.
2. you should avoid creating objects inside an event handler that is going to be called often; say you need a few brushes, just create them once and keep them around.
3. There are a whole lot of stock objects available at no extra charge, see classes such as Pens and Brushes . (and no, you don't dispose them, they aren't yours, you just borrow them).
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Please use <PRE> tags for code snippets, they improve readability. CP Vanity has been updated to V2.3
|
|
|
|
|
Hi,
RegistryKey.openSubKey("KeyName",true) working in windows XP , but it is not working in
Windows 7 32 bit. we are getting error : no rights to read.Please suggest me better way
|
|
|
|
|