基类中的派生实例

4
class baseClass
{
    derivedClass nm = new derivedClass();
}

class derivedClass : baseClass
{
}

这段代码可以成功构建。C#允许在baseClass中创建derivedClass对象,可能的原因是什么?您是否能想到任何特定的原因来进行这样做呢?

你为什么认为C#应该限制那个? - yogi
你知道有哪些面向对象的编程语言会限制这个吗?这并没有什么特别的。 - Mohammad Dehghan
@MD.Unicorn:不,我不知道有任何限制此功能的编程语言。但是如果这不会有用,为什么它们不限制呢?如果出于某些原因我们可以使用它,请告诉我原因。 - Deepak Raj
不能想到用途不是禁止某物的好理由。我发现有很多类都被封闭了,因为原始开发人员想不到你会继承它的情况... - Aron
我的观点与此类似:“抽象方法不包含具体实现,因此不能由基类实现。因此,派生类必须重写它,而不能简单地使用基类中定义的版本。很明显,抽象方法自动是虚拟的,不需要使用虚拟修饰符。事实上,使用虚拟和抽象修饰符是错误的。”(来自完全参考书的短语)。好吧,现在看看这个的用例,我认为我现在可以接受它了。 - Deepak Raj
显示剩余2条评论
4个回答

12

这段代码可以成功编译。

是的,你认为它不能吗?

C#允许在基类中创建派生类对象的可能原因是什么。

因为没有理由禁止它。

你能想到任何具体的原因吗?

例如静态工厂方法?

// BaseClass gets to decide which concrete class to return
public static BaseClass GetInstance()
{
    return new DerivedClass();
}

这其实是一种常见的模式。例如,在Noda Time中,我们经常使用它,其中CalendarSystem是一个公共抽象类,但所有具体派生类都是内部的。
当然,像你给出的确切示例那样使用实例字段初始化自己,通过创建派生类的实例会导致递归而使堆栈溢出,这很疯狂,但这并不是派生类的问题。通过初始化相同的类,您将获得相同的结果:
class Bang
{
    // Recursively call constructor until the stack overflows.
    Bang bang = new Bang();
}

如果一个方法是静态的,那么它不是工厂方法,你可能需要编写静态工厂或创建方法。 - TalentTuner
@Saurabh:已更改为“静态工厂方法”,但老实说,我不确定在这里区分是否有多大好处。 - Jon Skeet
我曾经在某处读到过以下区别: 创建方法:一个静态或非静态方法,用于创建(或克隆)类的实例。 工厂方法:在层次结构中定义和实现的一种方法,用于提供某个类类型的多态创建。 - TalentTuner
@Saurabh:嗯,工厂方法的维基百科页面包括类似的例子,它们称之为“静态工厂方法”。他们指出这不符合工厂方法模式,因为没有多态性,但是在我看来意思很清楚。 (顺便问一下,为什么你要在评论前加上“:”?) - Jon Skeet
@user1416420:“当然,使用你所举的确切例子是很疯狂的,因为它会由于递归而使堆栈溢出”,这种说法怎么就不能清晰地表明堆栈会溢出呢? - Jon Skeet
@user1416420:我并不认为我在暗示任何事情,因为我谈到的是“你给出的确切例子”,它并没有使用工厂方法。我会澄清一下,但我真的认为如果你读我写的东西,那里并没有这样的暗示... - Jon Skeet

1

我曾经与一位开发者共事,他在我们的代码库中编写了这段代码。我个人认为它很有用。

public class Foo
{
    public static Foo MagicalFooValue
    {
        get { return Bar.Instance; }
    }

    private class Bar : Foo
    {
        //Implemented as a private singleton
    }
}

0
一个明显的情况是在基类中有一个工厂方法,根据某些条件返回适当的实现。

0

derivedClass 可以在 baseClass 中实例化,因为它是一个可访问的类。C# 没有限制你这样做的理由。同样地,在 baseClass 内部也可以创建 baseClass 的实例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接