受保护的静态方法可见性
本文关键字:可见性 静态方法 受保护 | 更新日期: 2023-09-27 18:01:02
考虑一下这种情况:(注意,为了简洁起见,省略了类型和方法体(
这让我在需要的时候连接到数据。
public abstract class DatabaseAccessor {
protected static object GetDataFromDatabase(...) {...}
protected static object UpdateSomething(...) {...}
}
这管理缓存——如果我向ServerCache请求资源,但它没有,那么ServerCache可以使用DatabaseAccessor来获得它所需要的。我不直接提供对缓存资源的访问。
public abstract class ServerCache : DatabaseAccessor {
private static object CachedResources;
protected static object GetFromCacheOrGetFresh(...) {...}
protected static void InvalidateCache(...) {...}
}
这是一种提供访问缓存数据或新数据、发送更新、使缓存资源无效/过期的方法的服务。
public class DepartmentsService : ServerCache {
public static object Read() {
...
return ServerCache.GetFromCacheOrGetFresh();
}
public static object Update(string id) {
...
DatabaseAccessor.UpdateSomething(...);
ServerCache.InvalidateCache(...);
return DepartmentsService.Read().Where(record => record.Id == id);
}
public static object Create(...){...}
}
这一直很有效,直到我需要创建额外的服务,就像上面的一样。事情是这样的:
public class EmployeeService : ServerCache {
...
public static object Create(object creation) {
//check first service to see if creation is valid
//by checking that the DepartmentsService contains creation.Department.
DepartmentsService.Read().Where(..... problem
}
}
在非派生类中调用DepartmentsService OUTSIDE of DepartmentsServices时,我能够看到ServerCache的所有受保护方法。
在设计中,WebApi控制器同时使用DepartmentsService和EmployeeService。控制器不是从ServerCache继承的,并且方法按预期隐藏。
仅仅因为DepartmentsService和EmployeesService都是从ServerCache派生的,这并不意味着EmployesService应该能够调用DepartmentsSService本质上私有的方法。
关于受保护的修饰符,我缺少什么
当protected与static一起使用时,我是否遗漏了一些细微之处
这是"方法隐藏"发生的时候吗
DepartmentsService
和EmployeeService
bot继承自ServerCache
,而其自身继承自DatabaseAccessor
。
EmployeeService
能看到什么
首先,它可以看到所有其他类的所有公共成员,包括DepartmentsService
。此外,它可以看到DatabaseAccessor
和ServerCache
的所有受保护方法,因为它在继承层次中低于它们。
这是它可以看到的列表:
protected static DatabaseAccessor.GetDataFromDatabase(...)
protected static DatabaseAccessor.UpdateSomething(...)
protected static ServerCache.GetFromCacheOrGetFresh(...)
protected static ServerCache.InvalidateCache(...)
public static DepartmentsService.Read()
public static DepartmentsService.Update(string id)
public static DepartmentsService.Create(...)
protected
成员被继承后会发生什么
它保持原样:基类的protected
成员。它在基类上下文中执行,除非它被new
-关键字(或virtual
和override
,在您的情况下是不允许的,因为它都声明为static
(覆盖。因此,它对父类的所有子类都可见。
这是一个需要注意的要点,也是liskov替换原则的驱动因素之一,该原则基本上说,应该能够将子类的实例分配给其基类的引用,然后调用基类成员,它的行为应该像期望基类实例的行为一样,而不知道这在现实中是子类实例。
让我用给定的例子向您展示这意味着什么,假设方法将而不是是static
:
DatabaseAcccessor accessor = new ServerCache();
var data = accessor.GetDataFromDatabase(...);
行为应与完全相同
ServerCache accessor = new ServerCache();
var data = accessor.GetDataFromDatabase(...);
因为您永远无法知道变量或参数是否引用了派生类型实例。
因此,在使用new
和override
时要始终小心,并且通常倾向于组合而非继承。
处理您的评论
如何防止DatabaseAccessor
的受保护方法从EmployeeService
调用到DepartmentService
这需要一点重组。我建议将ServerCache设置为Singleton或Monostate。让我们去辛格尔顿:
public class ServerCache : DatabaseAccessor {
private object CachedResources;
private static readonly ServerCache instance;
private ServerCache(){ /* private ctor to prevent instances from beeing createt anywhere but in this class */ }
private static ServerCache Instance
{
get
{
if(instance==null)
instance = new ServerCache();
return instance;
}
}
public object GetFromCacheOrGetFresh(...) {...}
public void InvalidateCache(...) {...}
}
现在可以在DepartmentsService
和EmployeeService
中创建ServerCache
变量,而不是从ServerCache
继承。这样一来,ServerCache
方法将不可用,例如DepartmentsService的protected
方法。