Абстрактный базовый класс или интерфейс? Ни один не кажется правильным
-
03-07-2019 - |
Вопрос
Учитывая следующий код:
using System.Collections.Generic;
static class Program {
static void Main() {
bar Bar = new bar();
baz Baz = new baz();
System.Console.WriteLine(
"We have {0} bars, rejoice!", bar.Cache.Count);
}
}
public abstract class foo {
public static List<foo> Cache = new List<foo>();
}
public class bar : foo {
public bar() { Cache.Add(this); }
}
public class baz : foo {
public baz() { Cache.Add(this); }
}
Вы получите (несколько ожидаемый) результат "У нас есть 2 бара, радуйтесь!".
Это невероятно, теперь у нас в два раза больше мест, где можно выпить пива (очевидно), но я действительно хочу, чтобы у каждого класса был свой кеш. Причина, по которой я не хочу просто реализовывать этот кеш в подклассе, заключается в том, что у меня также есть некоторые методы в моем абстрактном классе, которые должны иметь возможность работать с кешем (а именно, выполнять итерацию по всем из них). Есть ли способ сделать это? Я рассмотрел использование интерфейса для foo
, но интерфейс не позволяет определять статические элементы как часть интерфейса.
Решение
Каждый производный класс foo должен определять, как / где получить кеш, поэтому каждый может (потенциально) иметь свой кеш. Методы в foo могут ссылаться на GetCache () без известной реализации.
public abstract class foo
{
public abstract ICache GetCache();
public void DoSomethingToCache()
{
ICache cache = this.GetCache();
cache.DoSomething();
}
}
public class bar : foo
{
public static ICache BarCache = new FooCache();
public override ICache GetCache()
{
return bar.BarCache;
}
}
public class FooCache : ICache { }
Другие советы
Используйте базовый базовый класс, параметризованный подклассом:
using System.Collections;
using System.Collections.Generic;
static class Program
{
static void Main()
{
bar Bar = new bar();
baz Baz = new baz();
System.Console.WriteLine(
"We have {0} bars, rejoice!", Bar.GetCache().Count);
}
}
public abstract class foo<T>
{
private static List<foo<T> > Cache = new List<foo<T> >();
public IList GetCache()
{
return Cache;
}
}
public class bar : foo<bar>
{
public bar() { GetCache().Add(this); }
}
public class baz : foo<baz>
{
public baz() { GetCache().Add(this); }
}
public abstract class foo {
public abstract List<foo> Cache { get; }
protected static Dictionary<Type, List<foo>> InnerCache = new Dictionary<Type, List<foo>>();
}
public class bar : foo {
public override List<foo> Cache {
get { return foo.InnerCache[typeof(bar)]; }
}
public bar() { Cache.Add(this); }
}
public class baz : foo {
public override List<foo> Cache {
get { return foo.InnerCache[typeof(baz)]; }
}
public baz() { Cache.Add(this); }
}
Вот ваш ответ:
using System;
using System.Collections.Generic;
static class Program
{
static void Main()
{
var bar = new Bar();
var baz = new Baz();
System.Console.WriteLine(
"We have {0} bars, rejoice!", Bar.Cache.Count);
bar.PrintList();
baz.PrintList();
}
}
public abstract class Foo<T>
{
public static List<T> Cache = new List<T>();
public void PrintList()
{
foreach(var item in Cache)
{
Console.WriteLine(item);
}
}
}
public class Bar : Foo<Bar>
{
public Bar() { Cache.Add(this); }
}
public class Baz : Foo<Baz>
{
public Baz() { Cache.Add(this); }
}
попробуйте это
using System.Collections.Generic;
using System;
static class Program
{
static void Main()
{
Bar bar = new Bar();
Baz baz = new Baz();
System.Console.WriteLine(
"We have {0} bars, rejoice!", bar.Cache.Count);
System.Console.ReadKey();
}
}
public abstract class Foo
{
public Foo()
{
Cache = new List<string>();
}
public List<String> Cache { get; set; }
}
public class Bar : Foo
{
public Bar()
{
Cache.Add("Bar");
}
}
public class Baz : Foo
{
public Baz() { Cache.Add("Baz"); }
}
Извините, мне пришлось поменять корпус ... У меня голова взорвалась