简体   繁体   English

在派生类中仅显示一些继承的方法

[英]Exposing only some inherited methods in the derived class

I stumbled across an interview question related to OOPS. 我偶然发现了与OOPS有关的面试问题。 Here is the question: There is a base class A with 5 methods. 这是一个问题:有一个基类A有5种方法。 Now how should I design the class such that if a class B inherits class A , only 3 methods are exposed. 现在我应该如何设计类,以便如果B类继承A类,则只暴露3个方法。 And if a class C inherits class A , the rest of the 2 methods are exposed. 如果C类继承了A类,则会暴露其余的2个方法。

Any thoughts ?? 有什么想法吗 ??

It should not be possible in any object-oriented language, otherwise it would break the Liskov substitution principle . 它不应该在任何面向对象的语言中,否则它将打破Liskov替换原则 Substituting a B for an A should not reduce its correctness (meaning methods should not suddenly be unavailable) B代替A不应该降低其正确性(意味着方法不应该突然不可用)

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? A中的5种方法是否必须公开?
  • Does the "exposition" by C need to be implicit or can the be explicitly exposed (eg pass-through) C的“阐述”是否需要隐含或可以明确暴露(例如传递)

Based on those answers you could either come up with possible options using internal , explicit interface implementations, etc. 基于这些答案,您可以使用internal ,显式接口实现等提出可能的选项。

if A is partial and you have 2 namespaces then: 如果A是部分的,那么你有2个名称空间:

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. 为实现这一目标,我们必须打破Liskov替代原则。 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. 在A虚拟中创建3个方法,然后在B中实现它们。然后在C中覆盖这2个方法。

Nobody says that the 5 methods of class A should be exposed when writing them. 没有人说在编写A类时应该暴露出A类的5种方法。 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. C#您可以简单地在A类中编写5个受保护的方法,并通过使用new修饰符编写一些隐藏方法来公开您希望可访问的方法 - 尽管这实际上不会直接暴露方法,它们只是被包装。

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. 你可以通过使用using关键字在C ++中实现它。 So, starting with class A: 所以,从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). 然后使用私有继承定义类B(基本上你不能从B自动转换为A,A中的所有公共方法都成为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: 对C类做同样的事情,而是暴露另外两种方法:

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: 或者,如果你应该通过C公开所有方法,只需使用公共继承,一切都存在:

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: 我上面提到的原因是因为你可以通过将B的实例明确地转换为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. 将A类定义为基类。 Have intermediate child classes A1 -> M1,M2,M3 and A2 -> M4, M5 deriving from Class A 有中间子类A1 - > M1,M2,M3和A2 - > M4,M5来自A类

Now, you can have 1) Class B inheriting A1 2) Class C inheriting A2 现在,您可以拥有1)B类继承A1 2)C类继承A2

These two classes are still derived from Class A. 这两个类仍然来自A类。

And also we are not breaking liskov substitution principle. 而且我们也没有打破liskov替代原则。

Hope, this gives clarity. 希望,这清楚了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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