Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 仅公开派生类中的某些继承方法_C#_Oop_Inheritance - Fatal编程技术网

C# 仅公开派生类中的某些继承方法

C# 仅公开派生类中的某些继承方法,c#,oop,inheritance,C#,Oop,Inheritance,我偶然发现了一个与OOPS有关的面试问题。问题是: 有一个基类a,包含5个方法。现在,我应该如何设计该类,以便如果一个类B继承了类a,那么只会公开3个方法。如果一个类C继承了类a,那么这两个方法中的其余部分将被公开 有什么想法吗?我也认为那是不可能的 但要给出一个大概的答案: 在虚拟中创建3个方法,然后在B中实现它们。然后在C中重写这2个方法。在任何面向对象的语言中都不可能这样做,否则它会破坏规则。用B替换a不应降低其正确性(意味着方法不应突然不可用) 然而,这个问题仍然存在一些模糊性,允许一些

我偶然发现了一个与OOPS有关的面试问题。问题是: 有一个基类
a
,包含5个方法。现在,我应该如何设计该类,以便如果一个类
B
继承了类
a
,那么只会公开3个方法。如果一个类
C
继承了类
a
,那么这两个方法中的其余部分将被公开


有什么想法吗?

我也认为那是不可能的

但要给出一个大概的答案:


在虚拟中创建3个方法,然后在B中实现它们。然后在C中重写这2个方法。

在任何面向对象的语言中都不可能这样做,否则它会破坏规则。用
B
替换
a
不应降低其正确性(意味着方法不应突然不可用)

然而,这个问题仍然存在一些模糊性,允许一些“开箱即用”的思维。以下是我想向面试官提出的问题:

  • 你说的“暴露”是什么意思
  • A中的5种方法必须公开吗
  • C的“解释”需要隐式的还是可以显式的公开(例如,通过)

基于这些答案,您可以使用
内部
、显式接口实现等提出可能的选项。

没有人说在编写类A的5个方法时应该公开它们。在
C#
中,您可以简单地在类A中编写5个受保护的方法,并通过编写一些隐藏方法来公开您希望可以访问的方法,就像这样-虽然这实际上不会直接公开这些方法,但它们只是包装好的

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();
    }
}

我认为这是一个诡计,甚至是愚蠢的问题。为了实现这一点,我们必须打破利斯科夫替代原则。您不应该呈现类的层次结构

也许你应该改用接口:

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();
}
class C: private A {
public:
    using A::Method4;
    using A::Method5;

};

我能想到的唯一方法是将它们全部私有化在A中,然后通过封装在BC中公开它们。。。但他们没有暴露,只是被处决了。。。所以它是对的一半。

如果
A
是部分的,并且您有两个名称空间,那么:

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
{ 

}
}

在您的评论中,您提到您对是否可以用其他语言进行此操作感兴趣。你可以通过使用关键字来做C++。因此,从A类开始:

class A {
public:
    int Method1() {     return 1;   }
    int Method2() {     return 2;   }
    int Method3() {     return 3;   }
    int Method4() {     return 4;   }
    int Method5() {     return 5;   }
};
然后使用私有继承定义类B(本质上,不能从B自动强制转换为A,而A中的所有公共方法将成为B中的私有方法)

对C类执行同样的操作,而是公开其他两个方法:

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();
}
class C: private A {
public:
    using A::Method4;
    using A::Method5;

};
或者,如果您想通过C公开所有方法,只需使用公共继承,一切都存在:

class C: public A {
public:

};
使用方法:

B *b = new B();
b->Method1();  // This works, Method1 is public
b->Method4();  // This fails to compile, Method4 is inaccessible
我上面提到的原因是,您可以通过显式地将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...

我知道,现在回应太晚了。只是想分享我的想法:

将类A定义为基类。 具有派生自类A的中间子类A1->M1、M2、M3和A2->M4、M5

现在,你可以 1) B类继承A1 2) C类继承A2

这两个类仍然派生自类A

而且我们也没有违反利斯科夫替换原理


希望,这让问题变得清晰。

受保护和隐私是“不要那样做”面试问题的允许答案?@svinja也许这是正确的问题。你知道,面试时人们问这些愚蠢的问题只是为了看看应聘者的回答。我认为这是一个骗人的问题。您不应该呈现类的层次结构。也许你应该改用接口。
新的public void Foo()
是否算作“暴露”
受保护的void Foo()
?2个“隐藏”的A方法仍将通过B暴露;他们只是没有被掩盖。谢谢你的回答。如果我们不继承,那怎么办。我有一个有5个或更多方法的a类。我想向类A添加新方法,并使其仅对某些其他类可用(可能是继承的或通过其他概念)。使用OOPS概念设计类似的东西是可能的。当然-你可以封装一个,并且只公开你想要的,但这与继承有很大的不同。好吧,我想这就是它。请举例说明。:)