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
DepartmentsService
and EmployeeService
bot inherit from ServerCache
which its self inherits from DatabaseAccessor
.
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(...)
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.
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.