C# - Can publicly inherited methods be hidden (e.g. made private to derived class)

前端 未结 10 1584
说谎
说谎 2020-12-04 19:00

Suppose I have BaseClass with public methods A and B, and I create DerivedClass through inheritance.

e.g.

public DerivedClass : BaseClass {}
<         


        
相关标签:
10条回答
  • 2020-12-04 19:40

    What you need is composition not inheritance.

    class Plane
    {
      public Fly() { .. }
      public string GetPilot() {...}
    }
    

    Now if you need a special kind of Plane, such as one that has PairOfWings = 2 but otherwise does everything a plane can.. You inherit plane. By this you declare that your derivation meets the contract of the base class and can be substituted without blinking wherever a base class is expected. e.g. LogFlight(Plane) would continue to work with a BiPlane instance.

    However if you just need the Fly behavior for a new Bird you want to create and are not willing to support the complete base class contract, you compose instead. In this case, refactor the behavior of methods to reuse into a new type Flight. Now create and hold references to this class in both Plane and Bird. You don't inherit because the Bird does not support the complete base class contract... ( e.g. it cannot provide GetPilot() ).

    For the same reason, you cannot reduce the visibility of base class methods when you override.. you can override and make a base private method public in the derivation but not vice versa. e.g. In this example, if I derive a type of Plane "BadPlane" and then override and "Hide" GetPilot() - make it private; a client method LogFlight(Plane p) will work for most Planes but will blow up for "BadPlane" if the implementation of LogFlight happens to need/call GetPilot(). Since all derivations of a base class are expected to be 'substitutable' wherever a base class param is expected, this has to be disallowed.

    0 讨论(0)
  • 2020-12-04 19:40

    I would say that if you have a codebase that you are wanting to do this with, it is not the best designed code base. It's typically a sign of a class in one level of the heirarchy needing a certain public signature while another class derived from that class doesn't need it.

    An upcoming coding paradigm is called "Composition over Inheritance." This plays directly off of the principles of object-oriented development (especially the Single Responsibility Principle and Open/Closed Principle).

    Unfortunately, the way a lot of us developers were taught object-orientation, we have formed a habit of immediately thinking about inheritance instead of composition. We tend to have larger classes that have many different responsibilities simply because they might be contained with the same "Real World" object. This can lead to class hierarchies that are 5+ levels deep.

    An unfortunate side-effect that developers don't normally think about when dealing with inheritance is that inheritance forms one of the strongest forms of dependencies that you can ever introduce into your code. Your derived class is now strongly dependant on the class it was inherited from. This can make your code more brittle in the long run and lead to confounding problems where changing a certain behavior in a base class breaks derived classes in obscure ways.

    One way to break your code up is through interfaces like mentioned in another answer. This is a smart thing to do anyways as you want a class's external dependencies to bind to abstractions, not concrete/derived types. This allows you to change the implementation without changing the interface, all without effecting a line of code in your dependent class.

    I would much rather than maintain a system with hundreds/thousands/even more classes that are all small and loosely-coupled, than deal with a system that makes heavy use of polymorphism/inheritance and has fewer classes that are more tightly coupled.

    Perhaps the best resource out there on object-oriented development is Robert C. Martin's book, Agile Software Development, Principles, Patterns, and Practices.

    0 讨论(0)
  • 2020-12-04 19:41

    @Brian R. Bondy pointed me to an interesting article on Hiding through inheritance and the new keyword.

    http://msdn.microsoft.com/en-us/library/aa691135(VS.71).aspx

    So as workaround I would suggest:

    class BaseClass
    {
        public void A()
        {
            Console.WriteLine("BaseClass.A");
        }
    
        public void B()
        {
            Console.WriteLine("BaseClass.B");
        }
    }
    
    class DerivedClass : BaseClass
    {
        new public void A()
        {
            throw new NotSupportedException();
        }
    
        new public void B()
        {
            throw new NotSupportedException();
        }
    
        public void C()
        {
            base.A();
            base.B();
        }
    }
    

    This way code like this will throw a NotSupportedException:

        DerivedClass d = new DerivedClass();
        d.A();
    
    0 讨论(0)
  • 2020-12-04 19:45

    When you, for instance, try to inherit from a List<object>, and you want to hide the direct Add(object _ob) member:

    // the only way to hide
    [Obsolete("This is not supported in this class.", true)]
    public new void Add(object _ob)
    {
        throw NotImplementedException("Don't use!!");
    }
    

    It's not really the most preferable solution, but it does the job. Intellisense still accepts, but at compile time you get an error:

    error CS0619: 'TestConsole.TestClass.Add(TestConsole.TestObject)' is obsolete: 'This is not supported in this class.'

    0 讨论(0)
提交回复
热议问题