I have an class named Foo. This class contains a collection of child objects of type FooChildBase, but I also have a further class of type FooChildTwo which inherits from FooChildBase.
Class Foo
Public Children As IList(Of FooChildBase)
End Class
Class FooChildBase
Public Info As String
End Class
Class FooChildTwo
Inherits FooChildBase
Public ExtraInfo As String
End Class
This all works fine. Now I need to use a specialisation of my Foo object with extra information.
Class FooSpecial
Inherits Foo
Public SpecialInfo As String
End Class
Class FooChildSpecial
Inherits FooChildBase
Public SpecialChildInfo As String
End Class
What I would like to do is have my FooSpecial Class treat it's Children collection as if they were FooChildSpecial objects, but still be able to add FooChildTwo objects to it. Is this possible and if so how can it be done?
EDIT
I think my original question was incorrect. I need to FooChildSpecial class to wrap any of the objects in the Children collection with the extra values, whether they are FooChildBase or FooChildTwo or XXX.
Hope this makes sense! Please let me know if more clarification is needed.
James
In order for FooSpecialChild to "Wrap" FooChildTwo, it either has to inherit from it or implement the same interface (IFooChildTwo). Unfortunately, you cannot conditionally inherit or implement ... it is either always or never. As such, your FooSpecialChild class can inherit from FooChildTwo, but then it will always be a FooChildTwo. Same if it implements the same interface as FooChildTwo.
The design pattern you laid out will work correctly. Since both FooChildSpecial and FooChildTwo inherit from the same base class, and the list is of that base class type, it will work out. You'll just have to check the type of the object when you're pulling from the .Children property.
After copy+pasting your code into a sample project, I could successfully do:
var foo = new Foo();
foo.Children = new List<FooChildBase>();
var special = new FooChildSpecial();
special.SpecialChildInfo = "special";
foo.Children.Add(special);
var two = new FooChildTwo();
two.ExtraInfo = "two";
foo.Children.Add(two);
Which shows that you can add both FooChildSpecial and FooChildTwo to your original list.
What do you mean by "treat as if they were FooChildSpecial" objects? Do you mean access methods that exist only in FooChildSpecial objects?
In this case you will need to cast them to FooChildSpecial.
However, it is better to just let FooSpecial treat them as FooChildBase objects, but have in FooChildSpecial and FooChildTwo that override the base methods to get different behaviors for the two subclasses.
I also have a feeling that you really don't need the FooSpecial class at all, but I could be wrong. I suspect that the extra information and special information could just be combined into "information" and if they need different types of information to initialize the class wtih the different types.
You could purhaps do it with generics that you have a base class which contains a list of Type T. When you define Foo and FooSpecial you spesify what T is.
Related
Is there a way that a derived class could inherit only a few of all the base class members..in C#?
If such maneuver is possible, please provide some example code.
Is there a way that a derived class could inherit only a few of all the base class members..in C#?
Yes. Make a base class that has one method, one constructor and one destructor. It has three new members, plus the heritable members of its base class. Now derive a class from that. The constructor and destructor will not be inherited; all the other members will. Therefore it is possible to create a derived class which inherits only some of its base class's members.
I suspect that answer is unsatisfying.
If your question is actually "is there a way that a base class can restrict what heritable members are inherited by a derived class?" the answer is no. Derived classes inherit all heritable members of base classes, regardless of their accessibility.
If your question is "is there a way that a derived class can choose which heritable members to inherit from a base class?" the answer is no. Derived classes inherit all heritable members of base classes, regardless of their accessibility.
Further reading, if this topic interests you:
https://ericlippert.com/2011/09/19/inheritance-and-representation/
When you make a type inherit from another, you get everything - both the good and the "bad" bits from the parent type ("bad", in this context, meaning something you didn't want to have).
You can hide something from the parent class in the child class through the new modifier. However, take this advice from years of experience... More often than not this leads to a lot of work being spent on doing workarounds in the way the child class works. You'll spare yourself from a lot of trouble if instead of going this way, you redesign your classes.
If a child type has to clip off functionalities from a parent type, you probably have a design flaw in the parent. Reshape it to have less funcionality. You can have its different features redistributed among different children. A class doesn't always have to be an only child, you know ;)
No, it's not possible. Do you imagine a Cat deriving Animal and the child (the Cat) deciding what's interesting from animals or not? A cat is an animal and this can't be changed.
BTW, interfaces can be used to hide details. For example:
public interface ISome
{
string Text { get; set; }
}
public class A : ISome
{
public string Text { get; set; }
public string Text2 { get; set; }
}
public class B : A
{
}
// This is an upcast. You're reducing the typing of an instance of B
ISome a = new B();
string text2 = a.Text2; // Error, Text2 isn't a property of ISome
string text = a.Text; // OK, Text is a property of ISome
I have a three classes A, B, and C shown below
public class A
{
public void add(int i, int k)
{
}
}
public class B:A
{
public void AddInt()
{
add(1, 2);
}
}
public class C
{
public void AddInt()
{
A objA = new A();
objA.add(1, 2);
}
}
We want access the "A" class method Add, there are two ways
1) Initiate the "A" class, then access the Add method
2) Inherit the "A" class, then access the Add method
If both those ways provide the same functionality, then why does C# provide two ways to achieve the same functionality.
What is the difference between initiating a class and inheriting a class?
First off, the word you're looking for is instantiate, not initiate.
What is the difference between instantiating a class and inheriting a class?
Inheritance expresses the "is a kind of" relationship between two classes:
The New York Times is a kind of newspaper.
A giraffe is a kind of animal.
An apple is a kind of fruit.
In each of these cases the first kind of thing is the "more derived" type -- it is more specific -- and the second thing is the "less derived" type, or "base" type. It is more general. More things are fruits than are apples.
In C# when you establish an inheritance relationship between two classes, you get two things:
Assignment compatibility: you can use an expression of the more derived type where an expression of the base type is needed.
Member inheritance: all methods, events, indexers, operators, fields, properties and nested types of the base class are automatically members of the derived class. (Constructors and destructors are not inheritable).
Instantiation is the process of making a new instance of a type.
Here, let me give you a copy of today's New York Times.
Here, let me give you a giraffe.
Here, let me give you an apple.
So in C#:
class Fruit {}
class Apple : Fruit { } // Apple inherits from Fruit
class Program {
static void Main() {
Apple apple = new Apple(); // Instantiating a new Apple
}
}
Make sense?
It's not about C# at all, it's about basic OOP concepts, that C#, in this case, simply manifests, being object oriented and strong typed language.
"Initialization" is a creation of an instance of a given type: A in your case.
Second example is a Polymorphism , where you derive from a given type A, and creating derived type B, is able to access public/protected members of the A class.
The access behaviour is the same in this case, but origin of that is completely different.
you are comparing Humans with food ... right no comparison
Initiating cost you some RAM of your system.
Inheriting lets you enable reuseability of common code
These two ways are available because your add method is public in class A. Change it to protected if you want to use it only in inherited classes. Simply saying inheritance makes all properties and methods except of private ones available in inherited classes. In your case class B is inherited from class A and instance of class B itself would be your instance to call method add on. In class C you simply created an instance of class A and called method add on it. All of this concepts would be much cleaner to you if you'll read about Access Modifiers and Inheritance.
Think of a class as a template, or plan, for how to build something. When you then use the template or plan to build one (think of architect plans for a house, and one of the many houses built from those plans), the words we use to describe this process are "Instantiation" and "Initialization".
You instantiate an instance of the object (build the house) using the class template (architects plan), and then initialize it (paint and decorate the house).
Inheritance, on the other hand, refers to something completely unrelated, in how classes are defined, using another existing class as a foundation or *base*line from which to start the definition of a new class that will extend the foundation or base class. When one class inherits from another, it means that "instances" of the derived class automatically get all the stuff that was defined in the parent base class without having to redefine it in the child.
A class is a type and acts as a template that allows you to create objects of this type. The creation of such objects is also called instantiation. This instantiation process involves allocating memory for this object (allocation) and then initializing this object, i.e. give its fields initial values. The latter is called initialization.
Inheritance is something completely different. Inheritance is about creating a new class (template) by inheriting existing code from a base class (also called superclass, or parent class).
This new derived class (also called subclass or child class) serves as template for the creation of a new type of objects.
The derived class can modify the behavior inherited from its base class and extend its possibilities. Inheritance creates a relation between the classes. Subclasses are assignment compatible with the superclasses above them in the inheritance hierarchy.
I would like to declare a property as:
IList<BaseNode and IComplexType> ComplexTypes { get; }
All elements in the list inherit from BaseNode and implement IComplexType. Is there any way to do this? It won't work to create a class BaseNodeComplexType because the nodes in the list are all sub-classes of BaseNode.
Update: I didn't think this through to explain fully. I have sub classes such as XmlNode. XmlNode inherits from BaseNode. I also have XmlComplexNode that inherits from XmlNode and implements IComplexType. But XmlNode does not inherit from IComplexType (and I don't want it to as I use "obj is IComplexType" in places. apologies for not adding this originally.
No, but you could solve it with generics?
class CustomObj<T> where T : BaseNode, IComplexType
{
IList<T> ComplexTypes { get; }
}
For more details about the used generic-constraints, see this page.
The correct behaviour would be to derive a new class i.e. ComplexBaseNode which has both the inherited features of BaseNode and interface IComplexType, would it not?
There's no direct way to do that.
But you can use generics to achieve that: what about a generic type parameter?
public class YourClass<T>
where T : BaseNode, IComplexType
... and your property will look like this:
IList<T> ComplexTypes { get; }
Where's your IList<> residing. If you use a generic parameter xxx (from your title), you can say where xxx : BaseNode, IComplexType.
Also consider if BaseNode could already implement IComplexType, possibly abstractly.
The definition of IList<T> means that you can only specify one type for the elements in the list.
Create a container class: ComplexNodeContainer<T,U>, that will contain BaseNode objects implementing also IComplexType, when T=BaseNode and U=IComplexType.
When you set the "contained" object(in the constructor preferably, or via a method/property), you can check whether it implements both types or not, and act accordingly.
You can have two properties to retrieve it, one as type T (or BaseNode), one as type U (or IComplexType in this case).
Then you can define your property as: IList<ComplexNodeContainer>
I have a base object abstract class and a base object collection class for some business objects to inherit from. I'm trying to figure out how to pass the base object type to the collection class (and other methods). I've been able to solve this by wrapping the class in an interface but i'm wondering if there is another way to do this or if using an interface is the best way. i think my question might make more sense from the code below.
i have a base class define -
public abstract class BaseObject<TYPE,KEY>:where TYPE:BaseObject<TYPE,KEY>, new()
public KEY ObjectId {get;protected set; }
i have a class that inherits from BaseObject
public class Customer : BaseObject<Customer,Guid>
My base collection class is -
public abstract class BaseObjectCollection<T> : List<T> where T: BaseObject, new()
I also have a few methods in other class that want to reference this baseclass -
public bool ValidateRule(BaseObject dataObject) {etc...}
If you use the base class in other classes that are not also generics, then I'm afraid that you're going to have to specify the type and key parameters for the object when you pass it to methods like ValidateRule.
In this design, an Interface implemented by the base object is probably the most appropriate solution. We use this pattern extensively in our code and it works quite well.
One other item you could explore is reducing the complexity of the base class slightly by moving the Key into the class as an overridable (or must override) property that defaults to a string or int or whatever may be appropriate. We found that this approach (we forced all collection keys to be strings) significantly reduced the class complexity.
I'm writing an interface that will be implemented by a lot of classes, and I'm writing a class that will hold a collection of instances of these implementations. Every class will have a default constructor.
So, is there a simple way (e.g. using some kind of reflection) to put an instance of each of these implementing classes to the collection? Besides doing it manually, which is simple, yes, but a lot of work and error prone (what if I missed an implementation while writing the method? What if a new implementation came and I forgot to update the given method?).
So, what I would like is to be able to iterate through all classes of a given namespace or maybe through the list of all available classes. My method then would simply check, through reflection, if the given class implements the given interface, and if it does, puts it into the collection.
Thank you.
You need to call Assembly.GetTypes() to get every class in an assembly, call typeof(IMyInterface).IsAssignableFrom to check for classes that implement the interface, then call Activator.CreateInstanse to instantiate the class.
Using LINQ:
typeof(IMyInterface).Assembly.GetTypes()
.Where<Type, bool>(typeof(IMyInterface).IsAssignableFrom)
.Select(t => Activator.CreateInstance(typeof(T)))
.ToArray()
Here it is without LinQ, spread out so you can see what's going on. But otherwise it's exactly the same as what SLaks wrote.
It get's all classes implementing the interface IFoo.
List<IFoo> items = new List<IFoo>();
//Iterate through all types
foreach (Type type in Assembly.GetExecutingAssembly.GetTypes) {
//Check the type is public and not abstract
if (!type.IsPublic | type.IsAbstract)
continue;
//Check if it implements the interface IFoo
if (typeof(IFoo).IsAssignableFrom(type)) {
//Create an instance of the class
//If the constructor has arguments put them after "type" like so:
//Activator.CreateInstance(type, arg1, arg2, arg3, etc...)
IFoo foo = (IFoo)Activator.CreateInstance(type);
//Add the instance to your collection
items.Add(foo);
}
}