daxu
daxu

Reputation: 4084

My child class's method not get called when initialised as Base

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

Answers (1)

Rob Kite
Rob Kite

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).

Interfaces

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

Generic Class

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

Related Questions