简体   繁体   中英

can we define a method in parent class which can be called within a child but not the other one

i ran into into a problem , i want to have a method(M) in a parent class (A) then B and C extend the class A . in this situation i want method(M) can be accessible by B but not C . any solution?

public class A
{
    ????? string M()
    {
        return "Hi there";
    }
}
public class B:A
{
}
public class C:A
{
}
B newClassB = new B();
C newClassC = new C();
Console.WriteLine(newClassB.M()); //the correct one
Console.WriteLine(newClassC.M()); //the incorrect one

Some of the other answers seem to encourage you to violate the Liskov Substitution Principle , which is very poor practice and will only lead to awful code.

What you have here is a design problem. If you want C to inherit A then it should behave exactly like an A but with added or modified functionality.

The Liskov Principle states:

"Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program."

With what you want to do, you could potentially break things. Lets say you have a method that accepts your parent class A , but you pass it a derived class C . What happens when your method attempts to call CM() ?

What you need to do is re-think your class design. Is a C really a subtype of an A if you aren't supposed to call M() from C ?

Your question's code is very vague so I cannot propose an alternate solution to your class structure, but I will edit if you can make your code less ambiguous.

Ok, a useful answer (my previous one was not).

No, you can't and you shouldn't do this, due to the Liskov Substitution Principle already pointed out in other answers and comments.

However, there are cases where it can be justified, and as a matter of fact, some classes in NET do implement the following pattern:

public class A
{
    public virtual bool CanCallM => true;
    public void M() {
        if (!CanCallM) throw new NotSupportedException();
        //do whatever }
}

public class B: A { }

public class C: A
{
    public override bool CanCallM => false;
}

Pretty? Not much, but you do give the consumer a way to know beforehand if M can be called, and you are ensuring at runtime that cM fails.

I personally prefer this pattern to simply doing nothing because the later is probably a bug in the code; someone is calling M with an expectation that is not met.

in this situation i want method(M) can be accessible by B but not C . any solution?

You can't do that, as I said in the comment, but you can do something like:

class A 
{

  public virtual bool Before() { return false; }

  public void BaseMethod () 
  {         
      if(Before())
         Console.WriteLine("Called method AMethod");
  }
}

class B : A 
{    
    public override bool Before() {return true; }
}

class C : A 
{    
}

void Main()
{
    var c = new C(); 
    var b = new B(); 

    c.BaseMethod(); 
    b.BaseMethod();
}

In this case BaseMethod() will be void execution for C instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM