Protected Static Method Visibility

后端 未结 1 2009
天涯浪人
天涯浪人 2021-01-27 09:33

Consider this situation: (Note that types and method bodies have been left out for brevity)

This gets me connected to data when I need to do that.

publi         


        
相关标签:
1条回答
  • 2021-01-27 09:45

    DepartmentsService and EmployeeService bot inherit from ServerCache which its self inherits from DatabaseAccessor.

    What can EmployeeService see?

    Well, first of all, it can see all public Members of all the other classes, including DepartmentsService. Furthermore, it can see all protected methods of DatabaseAccessor and ServerCache, since it is below them in inheritance hierachy.

    This is the list of what it can see:

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

    What happens to a protected member after it is being inherited?

    It stays beeing what it is: a protected member of the base-class. It is executed in the base classes context unless it is beeing overridden with the new-keyword (or virtual and override, which is not allowed in your case because it is all declared static). So it is visible to all child-classes of the parent class.

    This is an essential point to notice and one of the drivers for liskov substitution principle, which basically says that one should be able to assign an instance of a child class to a reference its base class, then call the base classes members and it should behave like one would expect a base class instance to behave, not knowing that is is a child class instance in reality.

    Let me show you what this means with the given example, assuming the methods would not be static:

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

    should behave exactly the same as:

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

    because you can never know, if an variable or parameter references to an derived type instance.

    Therefore, always be careful when using new and override, and generally favor composition over inheritance.

    To address your Comment

    How could you prevent protected methods of DatabaseAccessor to be called on DepartmentService from EmployeeService?

    This requires a little bit of reorganisation. I would recommend to make ServerCache Singleton or Monostate. Lets go for 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(...) {...}
    }
    

    You can now create ServerCache variables inside DepartmentsService and EmployeeService instead of inheriting from ServerCache. This way the ServerCache methods will not be available as protected methods of DepartementsService for example.

    0 讨论(0)
提交回复
热议问题