- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个不可变类型,我想创建它的一个子类,它可以访问所有相同的方法。
但是,由于必须如何实现不可变类,基类方法返回我的父类型,而不是我的子类型。是否可以创建一个不可变类,该类可以具有返回子类的子类?
下面是在 LinqPad 中运行的示例代码,用于演示问题
void Main()
{
var immutable = new MyImmutable(new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, -5 },
{ ImmutableKey.Key3, 1.25m },
});
var immutable2 = new MyImmutable(new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, 2 },
{ ImmutableKey.Key3, 3 },
});
var added = immutable.Apply((a, b) => a + b, immutable2);
added[ImmutableKey.Key1].Dump();
added[ImmutableKey.Key2].Dump();
added[ImmutableKey.Key3].Dump();
var subImmutable1 = new SubImmutable(1, new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, -5 },
{ ImmutableKey.Key3, 1.25m },
});
var subImmutable2 = new SubImmutable(1, new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, 2 },
{ ImmutableKey.Key3, 3 },
});
var subImmutableAdded = subImmutable1.Apply((a, b) => a + b, subImmutable2);
subImmutableAdded.GetType().Name.Dump(); //prints MyImmutable, it's not a SubImmutable
//after adding two SubImmutables, the type is changed back to the base type
var asSub = (SubImmutable)subImmutableAdded; // Unable to cast object of type 'MyImmutable' to type 'SubImmutable', SomeOtherValue was lost.
}
public enum ImmutableKey
{
Key1,
Key2,
Key3
}
public class MyImmutable
{
protected static readonly IEnumerable<ImmutableKey> AllKeys = Enum.GetValues(typeof(ImmutableKey)).Cast<ImmutableKey>();
private Dictionary<ImmutableKey, decimal> _dict { get; set; }
public MyImmutable(Dictionary<ImmutableKey,decimal> d)
{
_dict = d;
}
public decimal this[ImmutableKey key]
{
get
{
if (_dict == null || !_dict.ContainsKey(key))
return 0;
return _dict[key];
}
}
public MyImmutable Apply(Func<decimal, decimal, decimal> aggFunc, MyImmutable y)
{
var aggregated = new Dictionary<ImmutableKey, decimal>(AllKeys.Count());
foreach (ImmutableKey bt in AllKeys)
{
aggregated[bt] = aggFunc(this[bt], y[bt]);
}
return new MyImmutable(aggregated);
}
}
public class SubImmutable : MyImmutable
{
public int SomeOtherValue { get; set; }
public SubImmutable(int someValue, Dictionary<ImmutableKey,decimal> d)
:base(d)
{
SomeOtherValue= someValue;
}
}
输出:
2
-3
4.25
MyImmutable
InvalidCastException: Unable to cast object of type 'MyImmutable' to type 'SubImmutable'.
有没有一种方法可以让我拥有一个继承的不可变类型,它可以继承基类型中的所有方法,而不必全部重新实现它们?
配套代码审查问题:https://codereview.stackexchange.com/questions/79380/inheriting-methods-of-an-immutable-type
最佳答案
您可以使用虚拟方法来获取新实例。
在基类中创建一个虚方法,该方法接受输入以创建基类的新实例并返回基类的新实例。然后在子类中覆盖它以生成子类需要的任何额外输入并返回子类的新实例。
public class MyImmutable
{
// other stuff
// add this method
protected virtual MyImmutable GetNew(Dictionary<ImmutableKey, decimal> d)
{
return new MyImmutable(d);
}
// modify this method as shown
public MyImmutable Apply(Func<decimal, decimal, decimal> aggFunc, MyImmutable y)
{
var aggregated = new Dictionary<ImmutableKey, decimal>(AllKeys.Count());
foreach (ImmutableKey bt in AllKeys)
{
aggregated[bt] = aggFunc(this[bt], y[bt]);
}
return GetNew(aggregated);
}
}
public class SubImmutable : MyImmutable
{
// other stuff
// add this method
protected override MyImmutable GetNew(Dictionary<ImmutableKey, decimal> d)
{
return new SubImmutable(SomeOtherValue, d);
}
}
这样,任何不关心子类额外内容的转换都不需要在子类中被覆盖。
一些转换可能仍然需要被覆盖。例如:
var one = new SubImmutable(1, alpha);
var two = new SubImmutable(2, alpha);
var test1 = one.Apply((a, b) => a + b, two);
var test2 = two.Apply((a, b) => a + b, one);
Console.WriteLine(test1[someKey] == test2[someKey]); // true
Console.WriteLine(test1.SomeOtherValue == test2.SomeOtherValue); // false
如果您希望 test1
和 test2
具有相同的 SomeOtherValue
,那么您必须执行 Apply
方法虚拟,然后在子类中覆盖它。
关于C# 不可变类子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28326884/
为什么禁用类型像 type t = A of int | B of string * mutable int 虽然允许此类类型: type t = A of int | B of string * i
我正在寻找一种类似结构的数据结构,我可以从中创建多个实例并具有某种类型提示而不是不可变的。 所以我有这样的东西: class ConnectionConfig(NamedTuple): nam
我需要转到引用的结构: class SearchKnot { var isWord : Bool = false var text : String = "" var to
如sec 10.4.3中所述 当控制进入执行时,执行以下步骤 功能对象F(调用者)中包含的功能代码的上下文 提供thisArg,而调用方提供argumentsList: 如
i make a game that start display Activity indicator And activity indicator bottom display UiLable wi
编辑:我在这里不断获得支持。只是为了记录,我认为这不再重要。自从我发布它以来我就不再需要它了。 我想在 Scala 中执行以下操作... def save(srcPath: String, destP
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
如果您在Kotlin中访问List类型的Java值,则将获得(Mutable)List!类型。 例如。: Java代码: public class Example { public stati
我编写了 str 类(内置)的以下扩展,以便执行以下操作:假设我有字符串 "Ciao" ,通过做"Ciao" - "a"我想要的结果是字符串 "Cio" 。这是执行此操作的代码,并且运行良好: cla
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
我正在为我的公司设计一个数据库来管理商业贷款。每笔贷款都可以有担保人,可以是个人或公司,在借款业务失败时作为财务支持。 我有 3 个表:Loan、Person 和 Company,它们存储明显的信息。
我使用二进制序列化从 C# 类中保存 F# 记录。一切正常: F#: type GameState = { LevelStatus : LevelStatus
import javax.swing.JOptionPane; public class HW { public static void main(String[] args) { Strin
使用 flatbuffer mutable 有多少性能损失? 是否“正确”使用 FlatBuffers 来拥有一个应该可编辑的对象/结构(即游戏状态) 在我的示例中,我现在有以下类: class Ga
std::function create_function (args...) { int x = initial_value (args...); return [x] () mut
我需要在 for 循环中找到用户输入的字符。我通常会这样做 如果(句子[i] == 'e') 但是因为在这里,'e' 将是一个单字母字符变量,我不知道如何获取要比较的值。我不能只输入 if (sent
我有一个这样的算法: let seed: Foo = ... let mut stack: Vec = Vec::new(); stack.push(&seed); while let Some(ne
这个问题可能看起来非常基础,但我很难弄清楚如何做。我有一个整数,我需要使用 for 循环来循环整数次。 首先,我尝试了—— fn main() { let number = 10; // An
如果我有以下结构: struct MyStruct { tuple: (i32, i32) }; 以及以下函数: // This will not compile fn function(&mut s
我希望在每个 session 的基础上指定列的默认值。下面的脚本不起作用,但描述了我想如何使用它。我目前使用的是 MySQL 5.5.28,但如果需要可以升级。 CREATE TABLE my_tbl
我是一名优秀的程序员,十分优秀!