In the course of eliminating a catastrophic gap in knowledge, I sketched a certain class, something like this (I don’t include designers and methods in the listing, the question is difficult to understand);
public class SomeFractal { public int Generation; public SomeFractal Parent { get; private set; } public SomeFractal Root { get { if (Generation == 0) return this; else return Parent.Root; } } List<Fractal> Children {get;} } This was done to refine the recursive algorithms, but I'm not talking about that.
There was an idea to describe several "fractal" classes, differing in details, and implementing a single interface, let it be IFractal. The interface must contain basic properties (parent, root, child branches).
Most properties naturally return a class object in which they are described (we have a fractal, remember?), Respectively, if I want them described in the interface, it must be covariant. It turns out like this:
interface IFractal <out T> where T : IFractal<T> { T Root { get; } T Parent { get; } IEnumerable<T> Children { get; } } Actually, there are no problems - the interface, of course, is implemented by the class described above:
class SomeFractal : IFractal<SomeFractal> The problems will begin if I want somewhere else to use a variable of type IFractal<T> to abstract away from the concrete implementing class. After all, I will have to specify the parameter T, which can only be a class that implements IFractal - that is, no abstraction is working; in this case it’s the same thing as using the class itself.
Are there any ways around this limitation? Maybe I could not in covariance?
Please do not discuss the feasibility of practical application, it is pure theorizing for educational purposes.
UPDATE
I will explain about non-generics with an example
interface IFractal { IFractal Root { get; } IEnumerable<IFractal> Children { get; } } class Fractal : IFractal { public IFractal Root { get { if (parent == null) return this; else return parent.Root; } } public IEnumerable<IFractal> Children { get; } private Fractal parent; private string prettyCoolField; public string GetRootField() { return Root.prettyCoolField; } } GetRootField() Will not work, because IFractal does not have a prettyCoolField field. return (Fractal)Root.prettyCoolField; also does not work. Or am I incorrectly driven type?
INonGenericFractalabstract interface, what do you lack, what do you need covariance for?IEnumerable<INonGenericFractal>andRoot/Parentgetters are both covariant. - VladDIEnumerable<INonGenericFractal>and getters will be of typeINonGenericFractal(interface), notNonGenericFractal(implementing class) - that is, it’s already like not a fractal - eastwing