使抽象类中的属性只能在子类的构造函数中设置?

huangapple go评论104阅读模式
英文:

Make property in abstract class only settable in constructor of child class?

问题

我在一个具体类中有一个仅支持get的属性。根据定义,该属性只能在该类的构造函数中设置。后来我决定将这个属性放到一个没有构造函数的抽象类中,而具体类继承自该抽象类。如何使现在在抽象类中的属性只能在子类的构造函数中设置?

不会起作用的解决方案:

  • 如果我给属性添加protected set修饰符,那么子类将具有比我要求的更多权限。
  • init不是一个选项,因为我只想在构造函数中设置它。
  • readonly不一定会起作用,因为我使用的是C# 7.3。

示例原始类:

  1. public class FooOriginal
  2. {
  3. public int IntHere { get; }
  4. }

示例抽象类:

  1. public abstract class FooAbstract
  2. {
  3. public int IntHere { get; }
  4. }

示例子类:

  1. public class FooChild : FooAbstract
  2. {
  3. public FooChild()
  4. {
  5. // 不会编译,因为IntHere是只读的。
  6. intHere = 3;
  7. }
  8. }
英文:

I have a get-only property in a concrete class. By definition, that can only be set in a constructor of that class. I later decide that I want this property to belong to a constructor-less abstract class that the concrete class inherits from. How can I make the property that is now in the abstract class only capable of being set within the constructors of the child classes?

Solutions that won't work:

  • If I give the property a protected set modifier, then allows the child class more power than I'm asking for.
  • init isn't an option because I only want it set in the constructor.
  • readonly won't always work, because I'm on C# 7.3.

Example original class:

  1. public class FooOriginal
  2. {
  3. public int IntHere { get; }
  4. }

Example abstract class:

  1. public abstract class FooAbstract
  2. {
  3. public int IntHere { get; }
  4. }

Example child class

  1. public class FooChild : FooAbstract
  2. {
  3. public FooChild()
  4. {
  5. // Won't compile because IntHere is get-only.
  6. intHere = 3;
  7. }
  8. }

答案1

得分: 4

为了实现这一点,您可以给基类添加一个构造函数,如果您喜欢,可以将其设置为protected

  1. public abstract class FooAbstract
  2. {
  3. public int IntHere { get; }
  4. protected FooAbstract(int intHere)
  5. {
  6. IntHere = intHere;
  7. }
  8. }

然后,您的旧类可以调用基类构造函数,例如:

  1. public class FooOriginal : FooAbstract
  2. {
  3. public FooOriginal(int intHere)
  4. : base(intHere) // <-- 这就是魔法
  5. {
  6. }
  7. }

或者,如果您想按照您的示例传递一个常量值:

  1. public FooOriginal() : base(3)
  2. {
  3. }
英文:

To achieve this, you can give the base class a constructor, you can make it protected if you like:

  1. public abstract class FooAbstract
  2. {
  3. public int IntHere { get; }
  4. protected FooAbstract(int intHere)
  5. {
  6. IntHere = intHere;
  7. }
  8. }

And your old can call the base class constructor, for example:

  1. public class FooOriginal : FooAbstract
  2. {
  3. public FooOriginal(int intHere)
  4. : base(intHere) // <-- This is the magic
  5. {
  6. }
  7. }

Or if you want to pass in a constant value as per your example:

  1. public FooOriginal() : base(3)
  2. {
  3. }

huangapple
  • 本文由 发表于 2023年6月27日 20:56:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76565099.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定