Ori Refael
Ori Refael

Reputation: 3018

c# method inheritance to direct child

I have the following classes:

public class Essentials 
{
    public void DoSomething() 
    {
         //doing base stuff...
    }
}

public class NetworkEssentials : Essentials 
{
    public void DoNetworkSomething()
    {
        //doing something
    }
}

public class someClass : NetworkEssentials
{
    public void DoSomeSomething()
    {
        base.DoSomething(); //The thing I would like to prevent, as to block this from happening.
//attention: i dont want to change methods names so it will call the first parent, i still want to maintain a different method names to each class type
    }
}

I want to prevent someClass from being able to invoke methods in its parent's parent, only allowing direct inherit classes to invoke its base methods.

Is there anyway to do it?

Additional explanation:

basically, i have some mandatory fields i require that each object have, but there are some objects, not all, i demand to have an extra mandatory field. lets call them 1 2 3 , whereas 1 is the top parent. i want class 3 to call a class 2 method and this class 2 method will call the class 1 method, because only class 2 have this "extra" field. class 1 cant handle with this field because it doesnt recognize it at all

Upvotes: 3

Views: 2348

Answers (5)

Jon Hanna
Jon Hanna

Reputation: 113242

You could use internal and have NetworkEssentials in the same assembly. (While .NET does have an access type for the intersection of internal and protected, which would be perfect here, C# does not, so you'll have to make do with internal [Update: As of C# 7.2 there is now private protected to use that intersection]).

You could have:

public class NetworkEssentials : Essentials 
{
  new protected void DoSomething() 
  {
    throw new InvalidOperationException();
  }
}

So the DoSomething is hidden as far as the child goes. (It can't be public in Essentials or else someClass can see it the same as any other code).

It is still possible to get to DoSomething with some convoluted approaches though, and it doesn't provide a compile-time block.

basically, i have some mandatory fields i require that each object have, but there are some objects, not all, i demand to have an extra mandatory field. lets call them 1 2 3 , whereas 1 is the top parent. i want class 3 to call a class 2 method and this class 2 method will call the class 1 method, because only class 2 have this "extra" field. class 1 cant handle with this field because it doesnt recognize it at all

Well, solve that problem then. If NetworkEssentials knows how to call DoSomething() correctly, just override DoSomething() appropriately:

public class Essentials
{
  public virtual void DoSomething()
  {
    //Do stuff with field 1
  }
}

public class NetworkEssentials : Essentials
{
  public override void DoSomething()
  {
    base.DoSomething(); // handle field 1
    // Code to handle other fields either here, before the call to base.DoSomething(), or both.
  }
}

Don't attempt to block calls to DoSomething(), but use virtual methods to ensure they do the right thing. This is necessary anyway because non-inheriting code calling DoSomething() still needs the correct behaviour.

Upvotes: 5

InBetween
InBetween

Reputation: 32750

I'm not sure what the issue is. Can't you solve this with plain old virtual and overriden methods?

public class Essentials 
{
    public virtual void DoSomething() 
    {
         //do what needs to be done at this level
    }
}

public class NetworkEssentials : Essentials 
{
    public override void DoSomething()
    {
        //do what needs to be done at this level
        base.DoSomething(); //launch what needs to be done at Essentials' level.
    }
}

public class someClass : NetworkEssentials
{
    public override DoSomething()
    {
        //do what needs to be done at this level
        base.DoSomething(); //launch what needs to be done at NetworkEssentials' level.
    }
}

Note that this way, the derived class can only call it's parent's implementation. There is no way you could skip a level in the hierarchy and get SomeClass to directly call Essentials.DoSomething bypassing NetworkEssentials.DoSomething.

This example will chain the execution of your DoSomething logic from top to bottom (from most derived to least derived). It is just as easy to chain the execution from bottom to top, simply call the base implementation before instead of after the logic specific to each class.

UPDATE

You could arguably abuse a little the type system to get the behaviour you want with the following pattern:

public class Essentials
{
    private void DoSomething()
    {
        //doing base stuff...
    }

    public class NetworkEssentials : Essentials
    {
        public void DoNetworkSomething()
        {
            //doing something
            base.DoSomething(); //Perfectly OK
        }
    }
}

public class SomeClass : Essentials.NetworkEssentials
{
    public void DoSomeSomething()
    {
       base.DoSomething(); //Compile time error
    }
}

This really whole setup looks wierd but I have very little information to asses if this is really justified.

Upvotes: 1

XtremeBytes
XtremeBytes

Reputation: 1497

You can add a new implementation for whatever method from the base that you want to override. In this case you can have a new implementation for Dosomething in networkessentials and any derived class call to that method will only go through the NetworkEssentials. It wont stop you from calling the method but you can stop it from making the call directly to the base class which in essence is what you are trying to do I guess

public class Essentials
{
    public void DoSomething() 
    {
         //doing base stuff...
    }
}

public class NetworkEssentials : Essentials
{
    public void DoNetworkSomething()
    {
        //doing something
    }

    protected new void DoSomething() 
    {
         
    }
}

public class someClass : NetworkEssentials
{
    public void DoSomeSomething()
    {
        base.DoSomething(); //This will go thru NetworkEssentials and not directly to Dosomething
    }
}

Upvotes: 1

Alexei Levenkov
Alexei Levenkov

Reputation: 100527

I think you are looking for virtual - if you override method in derived class than children of that derived class will only be able to call derived's implementation (and there is absolutely no way to call top level one):

public class Essentials 
{
    virtual public void DoSomething() 
    {
         //doing base stuff...
    }
}

public class NetworkEssentials : Essentials 
{
    override public void DoSomething() 
    {
       base.DoSomething();
       // and other struff
    }

    public void DoNetworkSomething()
    {
        //doing something
    }
}

public class someClass : NetworkEssentials
{
    public void DoSomeSomething()
    {
        // can ONLY call nearest parent's that implements DoSomething 
        // so next calls NetworkEssentials.DoSomething 
        base.DoSomething(); 
    }
}

Upvotes: 1

BradleyDotNET
BradleyDotNET

Reputation: 61349

No, with that inheritance structure you can't do that. As @MobyDisk noted, you may consider using composition instead of inheritance to accomplish this task.

You can mark methods as protected to restrict access to only derived classes, but there is no way to force derived classes of derived classes to not have access.

Makes sense, really. If you have an Animal with an Eat method, Dog would have access to that, and so should Beagle (which would derive from Dog).

Even using method hiding doesn't work.

public class Essentials
{
    protected void DoSomething()
    {
        //doing base stuff...
    }
}

public class NetworkEssentials : Essentials
{
    public void DoNetworkSomething()
    {
        //doing something
    }

    private new void DoSomething()
    {

    }
}

public class someClass : NetworkEssentials
{
    public void DoSomeSomething()
    {
        base.DoSomething(); //The thing I would like to prevent
    }
}

Compiles just fine.

Upvotes: 0

Related Questions