Reputation: 4084
Think my understanding about OO is wrong.
Say I have these classes
public class BaseValidator{
public Result Validate(BaseRequest r){
xxxx
}
}
public class BaseRequest{
}
Then in my child class, I have this:
Public class ChildValidator : BaseValidator{
public Result Validate(ChildRequest r){
xxxx,
base.Validate(r);
}
}
public class ChildRequest: BaseRequest{
}
When using the classes:
BaseValidator cr = new ChildValidator();
ChildRequest r = new ChildRequest();
cr.Validate(r);
I thought this will call ChildValidator
's Validate
method, but turned out it calls BaseValidator
's method.
What is the right way to do this? I want to pass my ChildValidator
to another method, which takes BaseValidator
as a parameter.
Upvotes: 0
Views: 74
Reputation: 395
You are currently casting ChildValidator
to BaseValidator
, as such you are calling BaseValidator.Validate(BaseRequest)
which at present has a different signature to ChildValidator.Validate(ChildRequest)
. You can pass an instance of ChildRequest
to either method without issue because it inherits from BaseRequest
.
Without this cast you would call ChildValidator.Validate()
as you are expecting:
ChildValidator cr = new ChildValidator();
ChildRequest r = new ChildRequest();
cr.Validate(r); // Calls ChildValidator.Validate() method
If you want the ChildValidator.Validate()
method to always be called then you would need to use a virtual / override method. You can't do that as your classes are currently written because you are accepting different parameter types (BaseRequest
and ChildRequest
).
You could utilise interfaces to help you out in this case, as shown below:
public interface IValidator {
bool Validate(IRequest r);
}
public class BaseValidator : IValidator {
public virtual bool Validate(IRequest r) {
return true;
}
}
public class ChildValidator : BaseValidator {
public override bool Validate(IRequest r) {
return base.Validate(r);
}
}
public interface IRequest { }
public class ChildRequest : BaseRequest { }
public class BaseRequest : IRequest { }
With the above classes / interfaces the original calls would work as follows:
BaseValidator cr = new ChildValidator(); // cast to BaseValidator
ChildRequest r = new ChildRequest();
cr.Validate(r); // Still calls ChildValidator.Validate() method
Alternatively, and as Jon Skeet pointed towards, you may want to look at implementing a generic Validator class. That could perhaps look something like the below:
public class Validator<T> where T : BaseRequest {
public bool Validate(T r) {
return true;
}
}
public class BaseRequest { }
public class ChildRequest : BaseRequest { }
You can use that as below:
var validator = new Validator<ChildRequest>();
ChildRequest request = new ChildRequest();
validator.Validate(r);
The best method for you will depend on the rest of your implementation and what the methods are doing.
Upvotes: 1