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

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

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

问题

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

不会起作用的解决方案:

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

示例原始类:

public class FooOriginal
{
   public int IntHere { get; }
}

示例抽象类:

public abstract class FooAbstract
{
   public int IntHere { get; }
}

示例子类:

public class FooChild : FooAbstract
{
   public FooChild()
   {
       // 不会编译,因为IntHere是只读的。
       intHere = 3;
   }
}
英文:

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:

public class FooOriginal
{
   public int IntHere { get; }
}

Example abstract class:

public abstract class FooAbstract
{
   public int IntHere { get; }
}

Example child class

public class FooChild : FooAbstract
{
   public FooChild()
   {
       // Won't compile because IntHere is get-only.
       intHere = 3;
   }
}

答案1

得分: 4

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

public abstract class FooAbstract
{
	public int IntHere { get; }

	protected FooAbstract(int intHere)
	{
		IntHere = intHere;
	}
}

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

public class FooOriginal : FooAbstract
{
	public FooOriginal(int intHere)
        : base(intHere) // <-- 这就是魔法
	{
		
	}
}

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

public FooOriginal() : base(3)
{
}
英文:

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

public abstract class FooAbstract
{
	public int IntHere { get; }

	protected FooAbstract(int intHere)
	{
		IntHere = intHere;
	}
}

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

public class FooOriginal : FooAbstract
{
	public FooOriginal(int intHere)
        : base(intHere) // <-- This is the magic
	{
		
	}
}

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

public FooOriginal() : base(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:

确定