Inheritance in c# question
I have some rudimentary question about inheritance in C#.
I h开发者_如何学JAVAave two classes. I want the child class to inherit all members of the base class (e.g. x and y), but it seems to use inheritance I should initialize the base constructor. If I define another x and y in child class so that i later initialize the base constructor so what is the use of inheritance? And what is the solution?
The other question is that I have two methods with the same signature in base and child class and i need to use both. What can i do?
class Base
{
int x;
int y;
string name;
public Base(int i,int j)
{
x = i;
y = j;
name="s";
}
}
class Child
{
public Base()
{
}
}
Your questions are not very clear, and the code is invalid [now fixed by the editor] but I am going to answer what I think you are asking.
To initialize fields of a base class in a derived class, you must call the base constructor from the constructor of your derived class:
class Base
{
private int x;
private int y;
// ...
public Base(int x, int y)
{
this.x = x;
this.y = y;
}
}
// option 1, pass in values as parameters to constructor:
class Child1
{
public Child(int x, int y)
: base(x, y) // this passes the values up to the base constructor
{
}
}
// option 2, pass literals to the base constructor:
class Child2
{
public Child()
: base(3, 4) // this passes the literal values 3 and 4 to the base constructor
{
}
}
// elsewhere
var child1 = new Child1(1, 2); // child1.x = 1, child1.y = 2
var child2 = new Child2(); // child2.x = 3, child2.y = 4
Now, regarding your second question regarding having a method in the derived class with the same name. If you wish to redefine the behaviour of a method, you should make it virtual in the base class and override it in the derived class, which you can see from the method called SomeAction
in this example:
class Base
{
public virtual void SomeAction()
{
Console.Out.WriteLine("Base.SomeAction");
}
public void DifferentAction()
{
Console.Out.WriteLine("Base.DifferentAction");
}
}
class Derived
{
// this is a normal override
public override void SomeAction()
{
Console.Out.WriteLine("Derivde.SomeAction");
}
// this is an advanced technique which you should try to avoid in most cases
public new void DifferentAcion()
{
Console.Out.WriteLine("Derived.DifferentAction");
}
}
// elsewhere
var base = new Base();
base.SomeAction(); // prints Base.SomeAction
base.DifferentAction(); // prints Base.DifferentAction
var derived = new Derived();
derived.SomeAction(); // prints Derived.SomeAction
derived.DifferentAction(); // prints Derived.DifferentAction
((Base) derived).SomeAction(); // prints Derived.SomeAction
((Base) derived).DifferentAction(); // prints Base.DifferentAction
If a method is overriden, then the new behaviour will be exhibited regardless of whether you reference it as the base type or the derived type.
(If you use the new
keyword, or don't put anything, then a new inheritance chain is created and the behaviour will depend upon whether you reference the object as the base type or the derived type. You can see this in the final two calls in the code above: for the overriden method the derived behaviour is used but for the method where 'new' was used the orginal behaviour is exhibited when the object is treated as a Base
.)
The main reason for using inheritance, is that you may have many classes, which have essentially the same functionality as the super class. By making them sub classes of a super class, you may put fields and methods in the super class which are then inherited by all the sub classes, thus allowing you to only write such methods and fields once, as opposed to as many times as you have sub classes.
Don't define x and y in the child class. They are already there if Child inherits from Base.
The base class constructor is always called when you instantiate a derived class. If the base class has a default constructor this will be call if you ommit an explicit call to a base class constructor.
E.g.
class Base
{
int x;
int y;
//default constructor
public Base()
{
x = -1;
y = -1;
}
public Base(int x, int y)
{
this.x = x;
this.y = y;
}
}
class Derived
{
public Derived()
{
}
}
this will compile and set the instance fields of derived to -1 when a Derived object is created. However if you omit the default constructor you will get a compile error like the one you describe. Now the compiler is not capable of autogenerating the call to the base constructor. I would know which parameters to call it with
base(x=??,y=??)
In general you should have public fields/properties with the same name declared multiple times this is almost always a strong design smell. If the base class has a protected,internal or public field/property so does the derived class (the internal has some odd cases). For methods you can hide the base class implementation of a mthod or override it. The latter is the more common and that requires the base definition to be either abstract or virtual e.g.
//this requires Base to be declared abstract as well
public abstract void AbstractMethod();
public virtual void VirtualMethod(){}
that enables you to write as follows in the DErived class
public override void AbstractMethod(){}
public override void VirtualMethod(){}
If you need to hide a method you can do that though it's generally discourage (see below for why) if you just redeclare the method the compiler will give you a warning but you can use new to tell the compiler you actually want to hide the method it will look like this:
public new void SomeHiddenMethod(){}
how ever this has a (potentially) hugh impact on the use of objects of that type
public void SomeMEthod(Derived d)
{
//this calls the implementation in Derived
d.SomeHiddenMethod();
Base b = d;
//this calls the implementation in Base
b.SomeHiddenMethod();
}
hiding methods thus makes it incredibly hard to reason about the code since calling the same method on the same object might has differing result even though the object hasn't changed state in between the two calls but simply because the declared type of the variable changed.
And a final note on inheritance you should avoid inheriting for functionality, in short that is just because you need the same functionality in two (unrelated) classes you shouldn't create a base class to hold that functionality, rather you should create a third class and inject and instance of that class (or similar approaches) and you should think a lot about Liskov substitutional principle when designing the public interface of a class when it's not sealed.
精彩评论