简体   繁体   中英

Exposing only some inherited methods in the derived class

I stumbled across an interview question related to OOPS. Here is the question: There is a base class A with 5 methods. Now how should I design the class such that if a class B inherits class A , only 3 methods are exposed. And if a class C inherits class A , the rest of the 2 methods are exposed.

Any thoughts ??

It should not be possible in any object-oriented language, otherwise it would break the Liskov substitution principle . Substituting a B for an A should not reduce its correctness (meaning methods should not suddenly be unavailable)

However, there is still some ambiguity in the question that allows for some "out-of-the-box" thinking. Here are questions I would pose back to the interviewer:

  • What do you mean by "exposed"?
  • Do the 5 methods in A have to be public?
  • Does the "exposition" by C need to be implicit or can the be explicitly exposed (eg pass-through)

Based on those answers you could either come up with possible options using internal , explicit interface implementations, etc.

if A is partial and you have 2 namespaces then:

namespace the_impossible
{
class Program
{
    static void Main(string[] args)
    {
        B b = new B();
        C c = new C();

        b.m1();
        b.m2();
        b.m3();

        c.m4();
        c.m5();
    }
}

namespace A_1
{
    public partial class A
    {
        public  void m1() { }
        public  void m2() { }
        public  void m3() { }
    }
}

namespace A_2
{
    public partial class A
    {
        public void m4() { }
        public void m5() { }
    }
}

class B : A_1.A 
{

}

class C : A_2.A
{ 

}
}

在此输入图像描述在此输入图像描述

I think it was a trick or even dumb question. To achieve this, we must break the Liskov substitution principle. You shouldn't preseve the hierarchy of the classes.

Maybe you just should use interfaces instead:

public class A {} //why we even need this class?

public class B : A, I3Methods
{
    public void Method1() { }
    public void Method2() { }   
    public void Method3() { }
}

public class C : A, I2Methods
{
    public void Method4() { }
    public void Method5() { }
}

public interface I3Methods
{
    void Method1();
    void Method2();
    void Method3();
}

public interface I2Methods
{
    void Method4();
    void Method5();
}

我能想到的唯一方法就是让它们在A中都是私有 ,然后通过BC中的封装来暴露它们......但是它们没有暴露,只是被执行......所以它是半对的。

I also think that's impossible.

But to give an approximate answer:

Make 3 methods in A virtual, then implement them in B. Then override those 2 methods in C.

Nobody says that the 5 methods of class A should be exposed when writing them. In C# you could simply write 5 protected methods in class A and expose those you wish to be accessible by writing some hiding methods with the new modifier like this - although this wouldn't actually expose the methods directly they are merely wrapped.

class A
{
    protected void M1() { }
    protected void M2() { }
    protected void M3() { }
    protected void M4() { }
    protected void M5() { }
}

class B : A
{
    public new void M1()
    {
        base.M1();
    }

    public new void M2()
    {
        base.M2();
    }

    public new void M3()
    {
        base.M3();
    }

}

class C : A
{
    public new void M4()
    {
        base.M4();
    }
    public new void M5()
    {
        base.M5();
    }
}

In your comments, you mentioned that you were interested if this could be done in any other language. You can kind of do it in C++ through the use of the using keyword. So, starting with class A:

class A {
public:
    int Method1() {     return 1;   }
    int Method2() {     return 2;   }
    int Method3() {     return 3;   }
    int Method4() {     return 4;   }
    int Method5() {     return 5;   }
};

Then you define class B, using private inheritance (essentially you can't auto cast from B to A and all public methods in A become private methods in B).

class B: private A {
public:
    // We want to expose methods 1,2,3 as public so change their accessibility
    // with the using keyword
    using A::Method1;
    using A::Method2;
    using A::Method3;

};

Do the same for class C, exposing the other two methods instead:

class C: private A {
public:
    using A::Method4;
    using A::Method5;

};

Or if you're supposed to expose all the methods through C, simply use public inheritance and everything exists:

class C: public A {
public:

};

For usage:

B *b = new B();
b->Method1();  // This works, Method1 is public
b->Method4();  // This fails to compile, Method4 is inaccessible

The reason I said kind of above is because you can work around it by explicitly casting the instance of B to an A:

A *brokena = b;  // This wouldn't compile because the typecast is inaccessible

A *a = (A*)b;    // This however does work because you're explicitly casting
a->Method4();    // And now you can call Method4 on b...

I know, it is to late to respond. Just thought of sharing my thoughts:

Define Class A as a base class. Have intermediate child classes A1 -> M1,M2,M3 and A2 -> M4, M5 deriving from Class A

Now, you can have 1) Class B inheriting A1 2) Class C inheriting A2

These two classes are still derived from Class A.

And also we are not breaking liskov substitution principle.

Hope, this gives clarity.

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