你能从抽象类访问具体类吗?

发布于 2024-10-21 06:24:42 字数 1565 浏览 3 评论 0原文

我有一个代表不可变值的抽象类。与字符串一样,不可变类具有看似更改实例的方法,但实际上只是返回一个包含更改的新实例。抽象类有一些具有某些默认行为的方法。我可以在抽象类中拥有这种创建修改实例并返回逻辑吗?我挂断了,因为我不知道该放什么???职位。看来我需要的是一个代表派生类型的类型 T 。有没有这样的模式可以解决这个问题?

public abstract class BaseImmutable
{
    public readonly object Value;

    protected BaseImmutable(object val)
    {
        Value = val;
    }

    public ??? ModifiyButNotReally()
    {
        object newValue = GetNewObjectFromOld(Value);
        return new ???(newValue);
    }
}

public class DerivedImmutable : BaseImmutable
{
    public DerivedImmutable(object val) : base(val)
    {
    }
}

答案

这比我想象的要容易。可以使方法通用而不使类通用。考虑到这一点,我们唯一要做的就是通过包含 new() 约束来限制泛型参数从基类继承,并要求它不是抽象的。我需要做的最后一步是使用反射来获取非无参数构造函数来创建一个新实例。我发现这个解决方案比 @Jason 建议的通用类答案更好,我后来了解到它被称为 奇怪的重复模板模式。它还避免了需要在单独的静态类中创建难以测试/最小起订量的扩展方法,如 @bottleneck 所建议的。然而,@bottleneck 的回答给了我解决方案的灵感,所以积分归他所有。

public abstract class BaseImmutable
{
    public readonly object Value;

    protected BaseImmutable(object val)
    {
        Value = val;
    }

    public T ModifiyButNotReally<T>() where T : BaseImmutable, new()
    {
        object newValue = GetNewObjectFromOld(Value);
        var ctor = typeof(T).GetConstructor(new[] { typeof(object) });
        return (T)ctor.Invoke(new object[] { newValue });
    }
}

public class DerivedImmutable : BaseImmutable
{
    public DerivedImmutable(object val) : base(val)
    {
    }
}

I have a abstract class which represents an immutable value. Like strings, the immutable class has methods which appear to change the instance, but really just return a new instance with the changes. The abstract class has some of these methods which have some default behavior. Can I have this kind of Create modified instance and return logic in the abstract class? I'm getting hung up because I don't know what to put in the ??? positions. It seems like what I need is a type T that represents the deriving type. Are there any such patterns out there to overcome this problem?

public abstract class BaseImmutable
{
    public readonly object Value;

    protected BaseImmutable(object val)
    {
        Value = val;
    }

    public ??? ModifiyButNotReally()
    {
        object newValue = GetNewObjectFromOld(Value);
        return new ???(newValue);
    }
}

public class DerivedImmutable : BaseImmutable
{
    public DerivedImmutable(object val) : base(val)
    {
    }
}

ANSWER

This was easier than I suspected. A method can be made generic without making the class generic. With that in mind the only thing we have to do is constrain the generic argument to inherit from the base class and require it not be abstract by including a new() constraint. One last step I needed to do was to use reflection to get the non-parameterless constructor to create a new instance. I found this solution to be better than the generic class answer suggested by @Jason, which I have since learned is known as the Curiously Recurring Template Pattern. It also avoids the need to create a difficult-to-test/moq extension method in a separate static class as suggested by @bottleneck. However, @bottleneck's answer is what gave me the inspiration for the solution so the points go to him.

public abstract class BaseImmutable
{
    public readonly object Value;

    protected BaseImmutable(object val)
    {
        Value = val;
    }

    public T ModifiyButNotReally<T>() where T : BaseImmutable, new()
    {
        object newValue = GetNewObjectFromOld(Value);
        var ctor = typeof(T).GetConstructor(new[] { typeof(object) });
        return (T)ctor.Invoke(new object[] { newValue });
    }
}

public class DerivedImmutable : BaseImmutable
{
    public DerivedImmutable(object val) : base(val)
    {
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

2024-10-28 06:24:42

也许扩展方法在这里合适?

public static T Modify<T>(this T immutable) where T:BaseImmutable{
    //work your magic here
    //return T something
}

Maybe an extension method would be in order here?

public static T Modify<T>(this T immutable) where T:BaseImmutable{
    //work your magic here
    //return T something
}
走走停停 2024-10-28 06:24:42

你可以这样做:

abstract class BaseImmutable<T> {
    // ... 
    public T ModifiedButNotReally() { // ... }
}

class DerivedImmutable : BaseImmutable<DerivedImmutable> { // ... }

我省略了大量细节。

也就是说,这确实有点难闻。基本上,我为您提供了一种解决问题的机制,只是我不清楚您正在建模的任何内容是否最好通过您拥有的设置进行建模。

You could do this:

abstract class BaseImmutable<T> {
    // ... 
    public T ModifiedButNotReally() { // ... }
}

class DerivedImmutable : BaseImmutable<DerivedImmutable> { // ... }

where I've elided a ton of details.

That said, this does smell kind of bad. Basically, I'm giving you a mechanism to solve your problem, it's just not clear to me that whatever you're modeling is best modeled by the setup that you have.

标点 2024-10-28 06:24:42

杰森的方法可能是您最好的选择。您必须向目标类型添加运行时类型测试(不安全转换),因为 C# 类型系统对此的表达能力不够,但它会起作用。

添加一些背景 - 您所要求的称为自我类型。它是在类型声明中引用当前实例的类型的能力。这在某些语言中可用 - 对于 Scala 示例,但不幸的是在 C# 中不可用。在具有 self 类型 的虚构 C# 中,您可以声明如下所示的虚拟方法:

public abstract class BaseImmutable {
  public abstract self GetNewObjectFromOld();
}

实现该方法的类 Foo 必须返回 Foo 作为结果。要查找更多信息和解决方法,您可以尝试搜索在 C# 中模拟自身类型的各种方法。

Jason's approach is probably the best option you have. You'll have to add runtime type test (unsafe cast) to the target type, because the C# type system isn't expressive enough for this, but it will work.

To add some background - what you're asking for is called self types. It is the ability to refer to the type of the current instance in the type declaration. This is available in some languages - for example Scala, but unfortunatelly not in C#. In a fictional C# with self types, you could declare a virtual method like this:

public abstract class BaseImmutable {
  public abstract self GetNewObjectFromOld();
}

A class Foo implementing the method would have to return Foo as the result. To find more information and workarounds, you could try searching for various approaches to emulate self types in C#.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文