Scaleable Fluent Interface with Inheritance - c#

I am trying to write a Fluent Interface API that can scale well. What structure would allow for strong types, inheritance, and state-full(as in the class type)?
For instance
class A
{
public A PerformFoo()
{
//do stuff
return this;
}
}
class B : A
{
}
I would like class B when calling PerformFoo to return B not A, ideally I would prefer to stay away from
public class B : A
{
public new B PerformFoo()
{
return (B)base.PerformFoo();
}
}
As to not have to override or new Every method in child classes. I believe I would need to use generics that use Type signatures.
I don't want to use extension methods but can't seem to get the structure right when doing it with casting (T) like in the answer for [a link]Fluent interfaces and inheritance in C#

If I understand correctly, the issue is that Method1 is not behaving the way you'd like, as it downcasts to A, preventing you from calling further methods. One way around this is to shadow the method in subclasses:
public class A
{
public A Method1()
{
return this;
}
}
public class B : A
{
public new B Method1()
{
return (B)base.Method1();
}
}

finally i figured out the structure
public class A {}
public class B : A {}
public class C<T> : A where T : C<T>
{/*most methods return T*/}
public class D:C<D>
{/*all methods return this*/}
public class E<T>:C<T> where T:E<T>
{/*all methods return T*/}
public class F:E<F>{}
now even specialized generics will still return the original caller

Related

How to prevent illegal ICloneable<T> inheritance in C#?

I have an interface :
public interface ICloneable<out T>
where T : ICloneable<T>
{
T Clone();
}
that should receive a type that implement this interface (as shown below).
And I can create a class that implement it :
public class Class : ICloneable<Class>
{
public Class Clone() { return (Class)MemberwiseClone(); }
}
Great !
But anyone can create a class that implement ICloneable<T> "wrong".
Does exist a way to prevent inheritance as shown below ? (2 examples)
public class Other : ICloneable<Class>
{
public Class Clone() { return new Class(); }
}
public class Other : Class, ICloneable<Class>
{
public Class Clone() { return (Other)MemberwiseClone(); }
}
And allow inheritance as shown below ? (any from 2 examples)
public class Other : ICloneable<Other>
{
public Other Clone() { return (Other)MemberwiseClone(); }
}
public class Other : Class, ICloneable<Other>
{
public Other Clone() { return (Other)MemberwiseClone(); }
}
You cannot overload a class, so:
public class Other : Class {}
public class Other : Class, IC<Other> {}
Will never work.
Now, I'm gonna pull a Jon Skeet and show how you could do this, but then discourage you from doing it. You could do something like this:
public class CloneableOther : Class, ICloneable<Other> { }
public class Other : CloneableOther
{
}
public class CloneableFoo : Class, ICloneable<Foo> { }
public class Foo : CloneableFoo
{
}
What this code is doing is effectively removing the generic parameter from the inheritance. Except, Foo can still do this: Foo : CloneableFoo, ICloneable<Other>, and now you'll have to create two classes for every ICloneable instance.
This goes into that why do you need this in the first place? It is a practice to do Foo : IInterface<Foo>, but there's no way to enforce it. Your best bet is to just do copy and paste and just be sure that the class matches.
Maybe another way is to have in the constructor of Class, a check to see if the type of ICloneable is the type of the class, and to throw an exception if it isn't, and that could sort've feel like a compile time error, if it's done earlier enough in the runtime.

Inheritance and functions with different return types

I have the following classes set up like this:
class Test
{
public virtual subSmallObject CreateSmallObject
{
return new subSmallObject();
}
}
abstract class subSmallObject
{ string test; }
class subSmallObjectA : subSmallObject
{ string testA; }
class subSmallObjectB : subSmallObject
{ string testB; }
Now, instead of using Test class everywhere, I need to use a derived class of Test, let's call them class TestA and TestB. Test A and B need to have the CreateSmallObject class return either subSmallObjectA or SubSmallObjectB.
So typically I could just do
class TestA : Test
{
override subSmallObject CreateSmallObject()
{
return new subSmallObjectA();
}
}
class TestB : Test
{
override subSmallObject CreateSmallObject()
{
return new subSmallObjectB();
}
}
But the problem is that I can't then cast the subSmallObject return from those to subSmallObjectA or subSmallObjectB, due tot he requirements of the task at hand (it would break a lot of things that I don't have control over. Those things expect either smallSubObjectA or subSmallObjectB). There will be shared elements between subSmallObjectA and subSmallObjectB. I don't want to eliminate the virtual function because some code will be repeated if there are two separate methods.
Is there any pattern or any practice out there that I'm missing? I'm a bit lost on this and such architectural changes are beyond me, since I don't really know the "proper" way to do this.
Not being able to cast the results of a method call is...strange.
If you absolutely can't, you could try a generic factory method:
class SubObject{
public string Data;
}
class SubObjectA{
}
class SubObjectB{
}
class Test{
T GetSubObject<T>() where T:SubObject,new()
{
return new T();
}
}
Used Like
SubObjectA so=testInstance.GetSubObject<SubObjectA>();
That way you don't have to have the cast at the call site. It's not gonna work if SubObject doesn't have a default constructor though.

How to force single inheritance?

I have two classes:
public class A
{
}
public sealed class B : A
{
}
And I want that only my B class (defined in the same assembly of A) can inherits A.
How can I do?
And I want that only my B class (defined in the same assembly of A) can inherits A. How can I do?
There is simply no need for inheritance then..
public sealed class B
{
//includes all methods of A and B
}
You can use a internal constructor, this prevents other assemblies from using your class.
public class A
{
internal A() { }
}
public sealed class B : A { }
And, if you don't care about performance:
public class A
{
public A()
{
Type c = GetType();
if (c != typeof(A) && c != typeof(B)) throw ....;
}
}
I suggest you use composition instead of inheritance to restrict the visibility of base type members.
If only B can inherit A, then do you really need inheritance in the first place?
If it's to split a class that became too big, you're not following good practice as it is not likely to have a single responsibility.
Now if for some awkward reason you actually do need this, you can try that:
public class B
{
private sealed class A : B
{
}
}
And tweak it to your needs.

C# cross referencing generic classes

I want two generic classes to be able to reference each other. I can't seem to get anything to compile. Tried this:
class Program
{
static void Main(string[] args)
{
}
public class ClassA<BT> where BT: ClassB<ClassA<BT>>
{
BT btvar;
}
public class ClassB<AT> where AT: ClassA<ClassB<AT>>
{
AT atvar;
}
}
This has a practical implementation, but I wanted to avoid a complicated explanation of my own code. I can create closed classes that obey the rule, I just can't seem to describe a generic class or interface for those closed instances.
As fas as I understand, this is impossible, and this is why:
You want A, with a template value of type B.
You want B, with a template value of type A.
If you create a new instance of A, the compiler has to check of T is of type B. To check if it's type B, it has to check if B is of type A, A of type B, etc etc.
You end up creating an endless loop.
The way I ended up doing it was by adding the class as one of its own type parameters. It's not too pretty, but it works.
public abstract class Saver<TSaver, TData>
where TSaver : Saver<TSaver, TData>
where TData : ISaveable<TData, TSaver>
{ ... }
public interface ISaveable<TData, TSaver>
where TData : ISaveable<TData, TSaver>
where TSaver : Saver<TSaver, TData>
{ ... }
public class WorkspaceWindow : ScalingWindow, ISaveable<WorkspaceWindow, WorkspaceWindowSaver>
{ ... }
public class WorkspaceWindowSaver : Saver<WorkspaceWindowSaver, WorkspaceWindow>
{ ... }
This is possible, the following is based on the answer to this question.
public class ClassA<BT, AT> :
where BT : ClassB<AT, BT>
where AT : ClassA<BT, AT>
{
BT btvar;
}
public class ClassB<AT, BT> :
where BT : ClassB<AT, BT>
where AT : ClassA<BT, AT>
{
AT atvar;
}
You won't be able to use the classes directly, you'll need to override them.
public ClassAImp : ClassA<ClassBImp, ClassAImp>
public ClassBImp : ClassB<ClassAImp, ClassBImp>
So you may as well make ClassA and ClassB abstract.
this will compile, but I would like to see you instantiate either ClassA or ClassB:
public class ClassA<TBt> where TBt : ClassB<TBt>
{
TBt _btvar;
}
public class ClassB<TAt> : ClassA<TAt> where TAt : ClassB<TAt>
{
TAt _atvar;
}
"Why would you want to?" sounds like a good question to me. The point of Generics it to allow you to abstract a class to allow it to use multiple types. If the constraint limits the type to a concrete type, you are only allowing the type and its subclasses. If you aren't doing this for subclasses, don't use generics. If you are, how about using an interface?
public interface IClassA<ITB> { }
public interface IClassB<ITA> { }
public class ClassA<AT,BT> : IClassA<BT> where BT : IClassB<AT>
{
BT btvar;
}
public class ClassB<BT,AT> : IClassB<AT> where AT : IClassA<BT>
{
AT atvar;
}
public class ClassADerivedClosed : ClassA<ClassADerivedClosed, ClassBDerivedClosed> { }
public class ClassBDerivedClosed : ClassB<ClassBDerivedClosed, ClassADerivedClosed> { }

I would like to override a method in C#, but I have a different signature

The base class user should access the original method
class A
public init()
The derived class user should aceess ONLY the derived method.
class B
public init(int info)
I cannot use "override" bc there's a different signature.
What options do I have so that the derived class user does not see two methods.
Notes.
All in all I just need two classes that share some code. Inheritance is not a must.
But simplicity for the user of B is a priority.
This is a big code smell (and violates some basic OOP tenets) and, to the best of my knowledge, can not be done in any language. In OOP, an instance of B is an instance of A; this is polymorphism. So if A has a public method named init accepting no parameters, then so does B.
What are you trying to do this for?
Edit: Now that you've added the edit that states that inheritance is not a must, just use composition to share code. Give B a private instance of A, for example.
According to the Liskov principle you simply cannot do that, because it would violate this principle. The best thing you can to is override init() in the derived class and make it throw an exception every time it's invoked, stating that the user should use init(int info) and rely on the test to catch the errors.
Why you can't simple replace the init() method or even make it protected?
The Liskov principle states (rephrased) that where an instance of class A is required, an isntance of class B extends A can be passed.
If a method expects A and wants to call init() on it and you pass B (which extends A) to it with a protected init() the method will fail. This is the reason why the code will not even compile.
What you're asking for is impossible, due to the nature of the type system. Any instance of B can be thought of as an A, so you can call any of A's methods (including Init()). The best you can do is overload Init() in B and throw an exception to catch this at runtime.
public class B
{
void Init()
{
throw new NotSupportedException();
}
}
Contrary to some answers/comments here, what you are asking for would have a real use if it existed:
class Derived : Base
{
This can be seen by considering the workaround:
class Derived
{
private Base _base = new Base();
In other words, it's not really a base class at all, but a hidden part of the implementation.
The downside with this workaround is: what Base has an abstract method that you have to supply? You have to write this:
class Derived
{
class ActualDerived : Base
{
// override abstract method(s)
}
private Base _base = new ActualDerived();
This is the whole point of private inheritance (as found in C++) - it's for situations when you want to inherit the implementation but not the "interface" (in the informal sense).
But in C#, it's not available.
Presumabely A and B have something in common. Can you factor that out into a different base class?
public class Base
{
... common stuff ...
}
public class A : Base
{
public void Init()
{
}
}
public class B : Base
{
public void Init(int info)
{
}
}
if you need polymorphism then references to Base or, better yet, Thomas' interface are the way to go.
Instead of inheritance, use an interface as a "middle man":
public interface IAllThatYouNeed
{
public void DoSomeStuff();
}
public class A : IAllThatYouNeed
{
public void Init() {
// do stuff
}
}
public class B : IAllThatYouNeed
{
public void Init(int info) {
// do stuff
}
}
it looks like it's not yet possible
i tried to do something like this:
public class B : A
{
private override void Init() { }
public void Init(int x)
{ }
}
but Init() it's still visible from the A class
There is no perfect solution here. Some possible ways to do it:
An approach would be to make A.Init() virtual, override it in B and make it throw a NotImplementedException/InvalidOperationException.
Init() stays visible, but the user finds out very quickly that it is not to be used (make it explicit that Init(int info) is to be used in the XML documentation and in the message of the exception).
If you don't care about the inheritance part and just want to use the functionalities of class A in class B, don't have B deriving from A and make B instantiate A and use its functionalities.
Edit:
You can use an interface implementing the common operations in order to retain inheritance while avoiding to implement Init() in B:
public interface IOperations
{
void DoStuff();
void Foo();
}
public class A : IOperations
{
public void Init()
{
// Do class A init stuff
}
#region IOperations Members
public void DoStuff()
{
// ...
}
public void Foo()
{
// ...
}
#endregion
}
public class B : IOperations
{
A _operations = new A();
public void Init(int initData)
{
_operations.Init();
// Do class B init stuff
}
#region IOperations Members
public void DoStuff()
{
_operations.DoStuff();
}
public void Foo()
{
_operations.Foo();
}
#endregion
}
This can be made even better by using a factory:
public static class OperationsFactory
{
public static IOperations CreateOperations()
{
A result = new A();
result.Init();
return result;
}
public static IOperations CreateOperations(int initData)
{
B result = new B();
result.Init(initData);
return result;
}
}
This way instantiation code is well encapsulated, the difference between the two Init() methods is hidden from the user code.

Categories