我有一个必须解决的接口实现: 这是一个例子:
interface ISettingsBase
{
string Name { get; set;}
DateTime TimeStamp { get; set; }
}
public class SettingsBase : ISettingsBase
{
public string Name { get; set; }
public DateTime TimeStamp { get; set; }
}
interface IWorkerBase
{
ISettingsBase Settings { get; set; }
}
public class WorkerBase: ISettingsBase
{
public ISettingsBase Settings { get; set; }
}
interface IExtendedSettings : ISettingsBase
{
string FilePath { get; set; }
}
interface IWorkerExtended : IWorkerBase
{
// This configuration property should respect those of
// the IWorkerBase and increase the features.
IExtendedSettings Settings { get; set; }
}
public class WorkerExtended : WorkerBase, IWorkerExtended
{
...
...
public IExtendedSettings Settings { get; set; }
}
问题是编译器告诉我WorkerExtended中存在错误,并且我不尊重IWorkerBase.Settings接口的实现。问题是我需要新的改进类也支持具有更多属性的配置。
答案 0 :(得分:4)
interface IWorkerBase
{
ISettingsBase Settings { get; set; }
}
interface IWorkerExtended : IWorkerBase
{
IExtendedSettings Settings { get; set; }
}
这已经存在问题,因为IWorkerExtended.Settings
将隐藏 Settings
IWorkerBase
成员所需的成员。因此,IWorkerExtended
的实施者仍需提供原始Settings
成员(类型为ISettingsBase
)才能过渡实施IWorkerBase
。
编译器会在这里警告你,因为这个成员隐藏在这里。通常这样做会是一个错误,因此您需要使用new
键盘表示您愿意这样做:
interface IWorkerExtended : IWorkerBase
{
new IExtendedSettings Settings { get; set; }
}
请注意,这对实施者没有影响。因此,在实现该接口时,您必须提供两个Settings
成员。您可以通过显式实现基接口来实现:
public class Worker : IWorkerExtended
{
public IExtendedSettings Settings { get; set; }
ISettingsBase IWorkerBase.Settings { get; set; }
}
原因很简单:Liskov substitution principle表示当IWorkerExtended
是IWorkerBase
的子类型时,IWorkerBase
类型的任何对象都可以替换为IWorkerExtended
类型的对象。现在考虑一下:
IWorkerBase baseWorker = GetExtendedWorker();
baseWorker.Settings = new SettingsBase(); // not extended
这仅适用于SettingsBase
Settings
IWorkerBase
SettingsBase
类型ISettingsBase
保证的类型ISettingsBase
IWorkerExtended
的子类型Settings
)。因此,为了将扩展工作者分配给基础工作者类型,需要保证可以为其设置// server should keep session data for AT LEAST 1 hour
ini_set('session.gc_maxlifetime', 3600);
// each client should remember their session id for EXACTLY 1 hour
session_set_cookie_params(3600);
session_start(); // ready to go!
。但如果它只是实现session_start();
$timeout = 7200; // Number of seconds until it times out.
// Check if the timeout field exists.
if(isset($_SESSION['timeout'])) {
// See if the number of seconds since the last
// visit is larger than the timeout period.
$duration = time() - (int)$_SESSION['timeout'];
if($duration > $timeout) {
// Destroy the session and restart it.
session_destroy();
session_start();
}
}
// Update the timout field with the current time.
$_SESSION['timeout'] = time();
,您可以将更具体的扩展设置分配给@echo off & Setlocal EnableDelayedExpansion
Set /A TotalNumLines=0
( For /R %1 %%F In (*.Txt) Do (
For /F %%N In ('Find /V /C "" ^<"%%F"') Do (
Echo %%F %%N
Set /A TotalNumLines+=%%N
)
)
Echo Total number of code lines for all files = !TotalNumLines!
) > log.txt
EndLocal
。
答案 1 :(得分:0)
接口意味着隐藏实现细节,而不是告诉消费者&#34;哦 - 是 - 这个家伙有一些额外的字段&#34;。
通常,像if (worker is IWorkerExtended)
这样的投射或类型检查表明您根本不需要接口。
我想说在这种情况下,你最好只有一堆worker
类实现一个空的IWorker
接口。
类似的东西:
public interface IWorker
{
}
public class SettingsBase
{
public string Name { get; set; }
public DateTime TimeStamp { get; set; }
}
public class ExtendedSettingsA : SettingsBase
{
public string FilePath { get; set; }
}
public class ExtendedSettingsB : SettingsBase
{
public string SomeOtherProp { get; set; }
}
public class WorkerBase : IWorker
{
public SettingsBase Settings { get; set; }
}
public class WorkerExtendedA : IWorker
{
public ExtendedSettingsA Settings { get; set; }
}
public class WorkerExtendedB : IWorker
{
public ExtendedSettingsB Settings { get; set; }
}
public class XmlLoader
{
public IWorker Load(string xml)
{
return null; // instance of WorkerBase or WorkerExtendedA or WorkerExtendedB
}
}
public class Consumer
{
public void Process(IWorker w)
{
if (w is WorkerBase)
{
WorkerBase wbase = w as WorkerBase;
string name = wbase.Settings.Name;
DateTime t = wbase.Settings.TimeStamp;
}
if (w is WorkerExtendedA)
{
WorkerExtendedA wa = w as WorkerExtendedA;
string name = wa.Settings.Name;
DateTime t = wa.Settings.TimeStamp;
string f = wa.Settings.FilePath;
}
if (w is WorkerExtendedB)
{
WorkerExtendedB wb = w as WorkerExtendedB;
string name = wb.Settings.Name;
DateTime t = wb.Settings.TimeStamp;
string other = wb.Settings.SomeOtherProp;
}
}
}