Is it ok to hide a static method?
I have an abstract Catalog class as follows. It has a static method OpenCatalog() which is used to return a specific concrete catalog based on the type of location provided. Once it has determined the type of catalog it then calls a specific OpenCatalog() method of the correct concrete catalog type. For example I may have an implementation of Catalog that is stored in a SQL database, or another which is stored in a file system. See the code below.
public abstract class Catalog
{
public static ICatalog OpenCatalog(string location, bool openReadOnly)
{
if(location is filePath)
{
return FileSystemCatalog.OpenCatalog(string location, bool openReadOnly);
}
else if(location is SQL server)
{
return SqlCatalog.OpenCatalog(string location, bool openReadOnly);
}
else
{
throw new ArgumentException("Unknown catalog type","location");
}
}
...
}
public abstract class FileSystemCatalog:Catalog
{
public static new ICatalog OpenCatalog(string location, bool openReadOnly)
{
//Deserializes and returns a catalog from the file system at the specified location
}
...
}
public abstract class SqlCatalog:Catalog
{
public static new ICatalog OpenCatalog(string location, bool openReadOnly)
{
//creates an returns an instances of a SqlCatalog linked to a database
//at the provided location
}
...
}
First in general is it ok to hide a static method? I know it's p开发者_如何学Goossible to do, but it also just seems like something that one shouldn't do very often. Also is this a valid example where it's ok to hide a static method, or is there a better way to do what I'm trying to do?
It looks like you are trying to create an abstract factory in a very awkward manner. What actually happens is you are violationg Single Responsibility Principle and mixing the catalog creation concern with the catalog concern. What you need to do is to make CatalogFactory
non-static class. This gives you the flexibility to whatever you please later on (eg Dependency Injection).
public class CatalogFactory {
public ICatalog CreateCatalog(string location, bool openReadOnly)
{
if(location is filePath)
{
return OpenFileCatalog(string location, bool openReadOnly);
}
else if(location is SQL server)
{
return OpenSqlCatalog(string location, bool openReadOnly);
}
else
{
throw new ArgumentException("Unknown catalog type","location");
}
}
FileSystemCatalog OpenFileCatalog(string location, bool openReadOnly) {
return new FileSystemCatalog{/*init*/};
}
SqlCatalog OpenSqlCatalog(string location, bool openReadOnly) {
return new SqlCatalog{/*init*/};
}
}
You aren't really hiding it because you can always do
Catalog.OpenCatalog(...);
If you want the base class version. In fact, static methods are associated with a specific class and aren't virtual. It's just a nice convenience that you can call static methods defined in a base class on the derived class.
I have never found an argument against the use of private/internal static methods in terms of "code smell".
A good practical example might be an extension method inside some sort of service/utility library that you want to only extend within that library.
internal static ShippingRateType ToShippingRateType(this ProviderShippingRateType rateType) { }
精彩评论