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.
Related
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
I'm writing an application in C#, and am wrestling with its implementation of generics. I have an inheritance hierarchy that is mirrored by another inheritance hierarchy (Models and View Models) like so:
class A_Content { }
class B_Content : A_Content
{
public string Bar;
}
class C_Content : A_Content
{
public string Foo;
}
class A { public A_Content content; }
class B : A { }
class C : A { }
public class Test
{
IList<A> A_Collection = new List<A>();
public Test()
{
B b = new B();
C c = new C();
b.content = new B_Content();
c.content = new C_Content();
A_Collection.Add(b);
A_Collection.Add(c);
}
}
This works well enough, but doesn't enforce any type constraints on content, which leaves me casting it to the proper derived class every time I want to use it. I'd like to coax the compiler into enforcing the constraint that B objects only have B_Content content. My first cut at that was:
class A_Content { }
class B_Content : A_Content
{
public string Bar;
}
class C_Content : A_Content
{
public string Foo;
}
class A { }
class B : A { B_Content content; }
class C : A { C_Content content; }
public class Test
{
IList<A> A_Collection = new List<A>();
public Test()
{
B b = new B();
C c = new C();
A_Collection.Add(b);
A_Collection.Add(c);
}
}
This works nicely, but means that I can't access the common elements of content when all I have is a collection of As. What I'd really like to do is something like:
abstract class A_Content { }
class B_Content : A_Content
{
public string Bar;
}
class C_Content : A_Content
{
public string Foo;
}
abstract class A<T> { T content; }
class B : A<B_Content> { }
class C : A<C_Content> { }
public class Test {
IList<A<A_Content>> A_Collection = new List<A<A_Content>>();
public Test()
{
B b = new B();
C c = new C();
A_Collection.Add(b);
A_Collection.Add(c);
}
}
This, however, produces an error complaining that B cannot be implicitly converted into an A. I've tried adding an explicit cast to no avail. Is there some way to express the constraints I'm looking for more elegantly than the second model?
It's not entirely clear what you're after. Are you trying to make it so that every instance of A has a Content property whose type is A_Content, every B has a Content property that's a B_Content, and so on? If so, you can't do that and have B/C/etc. inherit from A. (not in a non-smelly way, anyway). The signature of A says that the Content property should be able to get (and, presumably, set) any valid value of A_Content. You cannot change the return type of a function or the type of a property or field in a derived class. You could use generics to basically defer the typing of the property all the way down to the usage of the class, but that syntax will be ugly and I'm not certain what it gets you.
For example, you could do this:
public class A<TContent> where TContent : A_Content
{
public TContent Content { get; set; }
}
public class B<TContent> : A<TContent> where TContent : B_Content
{
// nothing here, as the property is already defined above in A
}
public class C<TContent> : A<TContent> where TContent : C_Content
{
// nothing here, as the property is already defined above in A
}
But this means two things:
Anywhere you use A, B, or C you must specify the actual type of TContent (so A_Content, B_Content, etc.). Which is a pain
There is absolutely nothing stopping you from doing something like A<B_Content> (which is, in fact, essentially what B is in this case, since we've added nothing to the class).
In short, I think you need to drop back and punt and come up with a new design.
By the way
The reason your second example doesn't fly (with the List) is because you've told the list that it needs to contain A<A_Content>. Since B<B_Content> doesn't satisfy that, it won't work. This is a typical variance question and it confuses a lot of people. But consider this scenario (this code will not compile; it's intended to be demonstrative of the underlying reason):
List<A<A_Content>> list = new List<A<A_Content>>();
list.Add(new B()); // this seems OK so far, right?
A<A_Content> foo = list[0];
foo.content = new A_Content():
This would obviously break, since foo in reality is a B<B_Content>, so the runtime wouldn't let you set content equal to anything other than an instance of B_Content (or something that inherits from it), but the signature of the class means you should be able to assign anything that'sA_Content` or inherits from it.
You can use an interface for this, along with explicit implementation of the interface's member(s):
abstract class A_Content {}
class B_Content : A_Content {}
class C_Content : A_Content {}
interface IA
{
A_Content content { get; }
}
abstract class A<T> : IA
where T : A_Content
{
T content;
A_Content.content { get { return this.content; } }
}
class B : A<B_Content> {}
class C : A<C_Content> {}
Then you can make a List<IA> to hold a homogeneous collection of B and C objects.
In fact, with C# 4 and higher, you could make the interface generic and covariant; then you can implement the interface implicitly (as long as you use a property rather than a field):
interface IA<out T>
{
T content { get; }
}
abstract class A<T> : IA<T>
where T : A_Content
{
T content { get; set; }
}
class B : A<B_Content> {}
class C : A<C_Content> {}
Now, B still cannot be converted to A<A_Content>, but it can be converted to IA<A_Content>, so you can use a List<IA<A_Content>> to hold your homogeneous collection of objects.
Well, compiler produces an error, because indeed B cannot be converted into A<A_Content>.
This is because A<A_Content> is not a superclass of B. The parent class of B class is A<B_Content>.
I am afraid you need to stick to casting. It is needed here, because you have list of As.
If you really want to avoid casting (I am not sure why you would like to), you can try with dynamic dispatch.
You can try creating a List<dynamic> instead of List<A>.
You will need at least C# 4.0, though.
Hope I right undertsood your intention, so
having a collection like this
IList<A> means that you would like to have a collection of A objects with different implementation scenarios.
That property if the property of a base type. That means that base type has to expose methods/properties => so state and behavior primitives which the child classes has to make a concrete implementation.
Something like this:
class A_Content { public virtual string Bar {get;set;} }
class B_Content : A_Content
{
public override string Bar {get;set;};
}
class C_Content : A_Content
{
public override string Bar {get;set};
}
and somewhere in the code:
public Test()
{
B b = new B();
C c = new C();
A_Collection.Add(b);
A_Collection.Add(c);
//so
A_Collection[0].Bar // B::Bar
A_Collection[1].Bar //C::Bar
}
And you do not need to cast to real object. Simple OOP approach.
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> { }
Let's say I have a classes, like that:
class A
{
public static int Count()
}
class B : A
{
}
class C : A
{
}
How can I hide this static method for class B but not for C?
You can't, basically. Heck, if it's public then anyone can call it.
You could make it protected which would allow it to be called from within B or C but not elsewhere... but you still couldn't differentiate between B and C.
You could do it by creating another class, let's call it Special, that inherits A. Then you would make C inherit from Special and B inherit from A. Also, you would have the static method protected, that means only classes that inherited Special will have access to it.
class A
{
}
class Special : A
{
protected static int Count()
}
class B : A
{
}
class C : Special
{
}
The only solution would be to change your class hierarchy. It's not worth the hassle and WTF moments you will get in code reviews it if you ask me.
class ABase
{
}
class A
{
public static int Count()
}
class B : ABase
{
}
class C : ABase
{
}
Consider in AssemblyOne
public class A
{
internal A (string s)
{ }
}
public class B : A
{
internal B (string s) : base(s)
{ }
}
In AssemblyTwo
public class C : B
{
// Can't do this - ctor in B is inaccessible
public C (string s) : base(s)
}
Obviously this is a code smell, but regardless of if being a bad idea is it possible to call the ctor of B from the ctor of C without changing AssemblyOne?
Ignore Assembly Two for the moment. You would not be able to instantiate an instance of class C, because it inherits from B, which there are no public constructors for.
So if you remove the inheritance issue from Class C, you'd still have an issue creating instances of class B outside of B's assembly due to protection levels. You could use reflection to create instances of B, though.
For the purposes of testing, I altered your classes as follows:
public class A
{
internal A(string s)
{
PropSetByConstructor = s;
}
public string PropSetByConstructor { get; set; }
}
public class B : A
{
internal B(string s)
: base(s)
{
PropSetByConstructor = "Set by B:" + s;
}
}
I then wrote a console app to test:
static void Main(string[] args)
{
System.Reflection.ConstructorInfo ci = typeof(B).GetConstructors(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)[0];
B B_Object = (B)ci.Invoke(new object[]{"is reflection evil?"});
Console.WriteLine(B_Object.PropSetByConstructor);
Console.ReadLine();
}
I would not recommend doing this, its just bad practice. I suppose in all things there are exceptions, and the exception here is possibly having to deal with a 3rd party library that you can't extend. This would give you a way to instantiate and debug, if not inherit.
This is not possible, even with reflection.
If a class has no accessible constructors, there is no way to create a class that inherits it.
No, you must change AssemblyOne.