class 的只读版本仅适用于非固有 classes
Readonly version of a class only for non inherent classes
我需要 class 的受保护属性版本。这意味着外部 classes 无法更改值,但固有 class 可以。
这是一个示例代码,如您所见,我使用的是"smelly bool solution"。我应该如何以更优雅的方式做到这一点?我希望有一些好的模式解决这个问题。
由于很多 "protected set" 答案而编辑:
这样做我将无法在非固有 classes 中设置 class 属性 并且构造函数期间的 IsReadOnly 属性 和值将无用.
public class Foo1
{
protected bool smellyBoolSolution = false;
public bool IsReadOnly { get; private set; }
private int x;
public int X
{
get { return x; }
set
{
CheckCanWrite();
x = value;
}
}
public Foo1(bool isReadOnly)
{
IsReadOnly = isReadOnly;
}
private void CheckCanWrite()
{
if (IsReadOnly && !smellyBoolSolution)
throw new InvalidOperationException("Class is read only.");
}
}
public class Foo2 : Foo1
{
public Foo2()
: base(true)
{
}
public void DoStuff()
{
int newX = 1;
//.... calculates new x
//Oh, using the smelly bool solution I can change my base class properties
base.smellyBoolSolution = true;
base.X = newX;
base.smellyBoolSolution = false;
}
}
//Usage
public class Foo3
{
public void DoStuff()
{
//Foo1 in writable version
Foo1 f = new Foo1(false);
f.X = 1;
//Foo2 inherents Foo1 and only Foo2 can change X
Foo2 f2 = new Foo2();
f2.X = 1; //Exception here.
}
}
使用受保护字段启用从基础和继承 类 写入,公开一个 public 只读 属性:
public class A
{
protected string FooField;
public string Foo { get { return FooField; } }
public A()
{
FooField = "A";
}
}
public class B : A
{
public B()
: base()
{
FooField = "B";
}
}
您甚至可以使用自动属性来做到这一点:
public class A
{
public string Foo { get; protected set; }
public A()
{
Foo = "A";
}
}
public class B : A
{
public B()
: base()
{
Foo = "B";
}
}
另见 Restricting Accessor Accessibility (C# Programming Guide)。
private int x
int X
{
public get { return x; }
protected set { x = value; }
}
甚至更短
int X { public get; protected set; }
这两个解决方案并不完全相同,因为第一个使用显式实现的属性,第二个使用自动实现的属性。
您的行为违反了Liskov substitution principle,应该避免。
通过从 Foo1
继承,class Foo2
承诺遵守超级 class Foo1
公开的接口。 IE。在 Foo1
上运行的方法不必关心接收到的输入实际上是 Foo1
还是 Foo2
。两种类型都暴露相同的接口,因此可以统一操作。
这就是为什么除了重新考虑您的设计之外,您的问题没有优雅的解决方案。
我需要 class 的受保护属性版本。这意味着外部 classes 无法更改值,但固有 class 可以。
这是一个示例代码,如您所见,我使用的是"smelly bool solution"。我应该如何以更优雅的方式做到这一点?我希望有一些好的模式解决这个问题。
由于很多 "protected set" 答案而编辑:
这样做我将无法在非固有 classes 中设置 class 属性 并且构造函数期间的 IsReadOnly 属性 和值将无用.
public class Foo1
{
protected bool smellyBoolSolution = false;
public bool IsReadOnly { get; private set; }
private int x;
public int X
{
get { return x; }
set
{
CheckCanWrite();
x = value;
}
}
public Foo1(bool isReadOnly)
{
IsReadOnly = isReadOnly;
}
private void CheckCanWrite()
{
if (IsReadOnly && !smellyBoolSolution)
throw new InvalidOperationException("Class is read only.");
}
}
public class Foo2 : Foo1
{
public Foo2()
: base(true)
{
}
public void DoStuff()
{
int newX = 1;
//.... calculates new x
//Oh, using the smelly bool solution I can change my base class properties
base.smellyBoolSolution = true;
base.X = newX;
base.smellyBoolSolution = false;
}
}
//Usage
public class Foo3
{
public void DoStuff()
{
//Foo1 in writable version
Foo1 f = new Foo1(false);
f.X = 1;
//Foo2 inherents Foo1 and only Foo2 can change X
Foo2 f2 = new Foo2();
f2.X = 1; //Exception here.
}
}
使用受保护字段启用从基础和继承 类 写入,公开一个 public 只读 属性:
public class A
{
protected string FooField;
public string Foo { get { return FooField; } }
public A()
{
FooField = "A";
}
}
public class B : A
{
public B()
: base()
{
FooField = "B";
}
}
您甚至可以使用自动属性来做到这一点:
public class A
{
public string Foo { get; protected set; }
public A()
{
Foo = "A";
}
}
public class B : A
{
public B()
: base()
{
Foo = "B";
}
}
另见 Restricting Accessor Accessibility (C# Programming Guide)。
private int x
int X
{
public get { return x; }
protected set { x = value; }
}
甚至更短
int X { public get; protected set; }
这两个解决方案并不完全相同,因为第一个使用显式实现的属性,第二个使用自动实现的属性。
您的行为违反了Liskov substitution principle,应该避免。
通过从 Foo1
继承,class Foo2
承诺遵守超级 class Foo1
公开的接口。 IE。在 Foo1
上运行的方法不必关心接收到的输入实际上是 Foo1
还是 Foo2
。两种类型都暴露相同的接口,因此可以统一操作。
这就是为什么除了重新考虑您的设计之外,您的问题没有优雅的解决方案。