受保护的静态方法可见性

时间:2015-07-03 05:17:48

标签: c#

考虑这种情况: (请注意,为简洁起见,省略了类型和方法体)

当我需要这样做时,这会让我与数据联系起来。

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的DepartmentsService OUTSIDE时,我能够看到ServerCache的所有受保护方法。

在设计中,Web Api控制器同时使用DepartmentsService和EmployeeService。控制器不从ServerCache继承,并且方法按预期隐藏。

因为DepartmentsService和EmployeesService都来自ServerCache,这不应该意味着EmployeesService应该能够调用DepartmentsService的本质私有方法。

我在这里想到的保护修饰符是什么?
当保护与静态一起使用时,我是否会遗漏一些细微差别? 这是"方法隐藏"会发生什么?

1 个答案:

答案 0 :(得分:3)

DepartmentsServiceEmployeeService僵尸程序继承自ServerCache,其自身继承自DatabaseAccessor

EmployeeService可以看到什么?

首先,它可以看到所有其他类的所有公共成员,包括DepartmentsService。此外,它可以看到DatabaseAccessorServerCache的所有受保护方法,因为它在继承层次结构中位于它们之下。

这是它可以看到的列表:

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 - 关键字(或virtualoverride覆盖,这在您的情况下是不允许的,因为它全部被声明为{{ 1}})。因此它对父类的所有子类都是可见的。

这是需要注意的基本点和liskov substitution principle的驱动程序之一,它基本上说应该能够将子类的实例分配给引用它的基类,然后调用基类成员,它的行为应该像人们期望基类实例的行为,而不是知道它实际上是一个子类实例。

让我告诉你这个给出的例子意味着什么,假设方法 static

static

的行为应完全相同:

DatabaseAcccessor accessor = new ServerCache();
var data = accessor.GetDataFromDatabase(...); 

因为如果变量或参数引用派生类型实例,你永远不会知道。

因此,在使用ServerCache accessor = new ServerCache(); var data = accessor.GetDataFromDatabase(...); new时务必小心,并且通常偏好合成而不是继承。

解决您的评论

您如何阻止override DatabaseAccessorDepartmentService调用EmployeeService的受保护方法?

这需要一点点重组。我建议制作ServerCache Singleton或Monostate。让我们选择Singleton:

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(...) {...}
}

您现在可以在ServerCacheDepartmentsService中创建EmployeeService个变量,而不是从ServerCache继承。这样,ServerCache方法将无法用作DepartementsService的protected方法。