Method Inheritance Prevention

I have a base class Foo, which is concrete and contains 30 methods that relate to its subclasses.

Now I am faced with a situation specific to the base class only, and I want to create a method that cannot be inherited, is this possible?

Class Foo { /* ... inheritable methods ... */ /* non-inheritable method */ public bool FooSpecificMethod() { return true; } } Class Bar : Foo { /* Bar specific methods */ } var bar = new Bar(); bar.FooSpecificMethod(); /* is there any way to get this to throw compiler error */ 

EDIT

I am not sure if I was originally originally.

I understand the principles of inheritance, and I understand the principle of Liskov substitution. In this case, there is a single exception that ONLY refers to the “non-inheritable” case, so I did not want to subclass uninheritedFoo.

I asked if it is technically possible to create a situation where foo.FooSpecificMethod () is a valid and public method, but subclassoffoo.FooSpecificMethod () throws a compiler error.

Essentially, I want to use a private method for an unsealed class.

+4
source share
9 answers

I would rethink the need for this.

If you use inheritance, you assume that "Bar" IS "Foo". If Bar is always Foo, methods that work on Foo should also work on Bar.

If this is not the case, I would rework it as a private method. In public, the bar should always be foo.


Just for this one more step -

If you could do this, it would be very difficult. Possible situations:

 Foo myBar = new Bar(); // This is legal myBar.FooSpecificMethod(); // What should this do? // It declared a Foo, but is acutally a Bar 

However, you can force this behavior to use reflection. I think this is a bad idea, but FooSpecificMethod () can check the type of this, and if it is not typeof (Foo), throw an exception. That would be very confusing and have a very bad smell.


Edit in response to a question:

It is not possible for the compiler to do what you ask. If you really want to force the compiler to check this and prevent it, you really should consider making Foo a hermetic class. In this case, you can use other extension methods than subclasses.

For example, you might consider using events or delegates to extend the behavior instead of allowing the object to be a subclass.

Trying to do what you do is basically trying to prevent the main goals of inheritance.

+11
source

Brian is right about Liskov Replacement (up). And Reed is right about "yes" (he also heaved); in fact they both tell you the same thing.

Your public methods are a contract with users of your Foo class saying that you can always call these methods in Foo.

A subclass of Foo means that you say that a subclass, for example. Bar, it is always acceptable to use where you can use Foo. In particular, this means that you do not (necessarily) inherit the implementation of Foo (you can override this, or Foo may be abstract and not give a concrete implementation for the method).

Inheritance of implementation (if any) is a detail; what you really inherit is the public interface, the contract, the promise of users that the panel can be used as Foo.

In fact, they may not even know that they have a Bar, not Foo: if I create a FooFactory and I write it Foo * getAFoo () to return a pointer to the panel, they may never know, and sholdn 't gotta.

When you break this contract, you break Object Orientation. (And the Java Collection classes, throwing NotSupported exceptions, completely break OO - users can no longer use the so-called subclasses polymorphically. This bad, poor design, which caused serious headaches for many many Java users, is not something to imitate.)

If there is a public method that cannot be used by subclasses of Foo, then this method must not be in Foo, it must be in a subclass of Foo, and other subclasses must be obtained from Foo.

Now this does NOT mean that all methods in Foo should be called in subclasses. No, I do not contradict myself. Non-public methods are not part of the public interface of the class.

If you want the method in Foo not to be called in Bar and not to be publicly called in Foo, make this method private or protected.

+5
source

No, this violates the principle of replacing Liskov .

Pragmatically, you can either "throw a NotImplementedException ()" in Bar, or remove a method from Foo and transfer it to the subclasses to which it applies.

+4
source

Providing a private function will not allow it to directly call subclasses.

If you are talking about virtual functions that you do not want to overload, marking the function as sealed at the point you want to block works.

Even if it is a private function, it can still be caused by reflection.

You can also declare a function on an interface and explicitly implement the interface in the class, which forces you to apply it to the interface to use this function.

+2
source

You can make a private function and then call it using reflection. Probably a little overboard. Anyway, just put the function in your base class along with comments saying that they should only be called from the base class. Perhaps even those good /// comments that come up with intellisense. Then you can get an error, but then it’s good, you will always get errors, and the best thing you can do is to document this situation in order to try to avoid it.

+1
source

The solution I used was to create a public inner inherited class. That way, it can access the private variables of the base class (as needed), and I don't need to publicly publish any of these private variables or functions (which I don't want).

Thanks so much for all your advice, it made me rethink exactly what I need from this arrangement.

0
source

There are two reasons why a derived class can hide members of the base class without violating the Liskov Substitution Principle:

  1. If the member in question is `protected`, it essentially represents a contract only between the parent and the derived classes. Thus, he does not impose any obligations on the derived class, with the exception of cases provided for by the contract with the parent. If public members of a base class rely on some non-public specific member of external instances that have some specific value, a derived class that changes the value of this member may violate the LSP, even if the member itself is not publicly available, since changing its value may change the behavior of public members who use it. However, in cases where the base class defines a protected element but does not use it, the derived class can do whatever it likes with this member without violating the LSP. The key point to understand with protected members is that the reason ToyotaCar should not alter the semantics of Car public members is because a link to ToyotaCar can be provided to the code that expects "Car" than "ToyotaCar". On the other hand, if ToyotaCar changes the behavior of the protected Car method in a way that is not exposed to any open members, the only code that can notice such a change is the code that is either in ToyotaCar or its derivative, and such a code will know that it has a ToyotaCar. Code that is in some other derivative of "Car" (for example, "FordCar") can access protected members of "Car", but is guaranteed * not * to access these methods on an instance of "ToyotaCar".
  2. It is sometimes useful for a base type or interface to display multiple members that will not apply to all implementation types. While the principle of interface separability suggests that kitchen sink interfaces should be avoided, there are times when such interfaces can be more practical than any alternative. For example, some types of the stream class may support different acknowledgment modes, but other types will not. If link streams are transmitted through code that does not care about establishing a connection, it may be easier to have a Stream class that includes an acknowledgment selection property that may or may not be used, than requiring the code to try to list the passed link to `IHandshakeSelector` and set `IHandshakeSelector.HandshakeMode` if so. On the other hand, if a particular stream class behaves the same for all handshake modes except XonXoff, which throws an exception if the code tries to set this, it might make sense for this class to hide the HandshakeMode property.

    I would say that while hiding an element of a base class is often a sign of poor design, there are times when hiding members of the base class would be more appropriate than exposing them; if the derived class cannot correctly use the protected method (as is the case with the MemberwiseClone method available for derivatives of List<T> ), there is no reason to MemberwiseClone it. Unfortunately, there is no absolutely clean way to hide such members. The best thing you can do is declare a public member with the same name (using the "new" modifier), which blocks all access to the base class member. For example, code might define a nested open static class named MemberwiseClone with no members. The EditorBrowseable attribute can be used to prevent Intellisense from displaying this nested class, but even if the code really tried to use this class, it has no members, and you cannot create a repository of this type, so it should be pretty harmless.

0
source

You should consider composing [ http://en.wikipedia.org/wiki/Composite_pattern } over inheritance if you want to achieve what you are trying to do and expose methods from a private object (that is, the one you are currently inheriting )

0
source

As others have noted, this is not possible, and most importantly, it is not necessary.

I ran into the same problem when I had the following structure:
- Parent class with properties of child classes.
- Different properties will be displayed in the child classes, but they all have the same initialization procedure, so I put the code in the parent class.

 public class Parent { public CHILD1 Child1; public CHILD2 Child2; public Parent(params args){ Child1 = new CHILD1(arg1, arg2); Child2 = new CHILD2(arg1, arg2); } //split here public Parent(object arg1, object arg2) { PropertyInfo[] list = this.GetType().GetProperties(); foreach (var pi in list) { pi.SetValue(this, BL.Method(arg1, arg2, this.GetType().Name, pi.Name) // get data } } } public class CHILD1 : Parent { public CHILD1(object arg1, object arg2) : base(arg1, arg2) { } public object C1Property1 { get; set; } public object C1Property2 { get; set; } // .. } public class CHILD2 : Parent { public CHILD2(object arg1, object arg2) : base(arg1, arg2) { } public object C2Property1 { get; set; } public object C2Property2 { get; set; } // .. } 

Now I could call parent.Child1.C1Property1 . But the code also allows calling the following: parent.Child1.Child1.Property1 , which makes no sense and Child1.Child1 exception, since the Child1.Child1 property Child1.Child1 always be null .

To fix this, I only had to break the code of the parent class into two classes:

  • One containing Child properties and calling child constructors
  • and one with design logic to populate the properties.
0
source

All Articles