I have something which should be easy to answer for most of your I think:
I have the following classes:
class One
{
string first;
}
class Two : One
{
string second;
}
Now I wanted to replace all One values of a Two value. So I tried the following:
One one = new One();
Two two = new Two();
two = (Two) one; // <= this seems to not work
So do I really have to implement a Method that copys all members of one to two?
One doesn't inherit from Two, and that is what is not working great.
Class inheritance doesn't mean to hide or to replace one class's property value, but that the derived class is a specialization of the base class it inherits from.
For example:
public class Cat {
}
public class Dog {
}
What do these two have in common?
They have four legs;
They are all animals;
They have hairs;
What do they not have in common?
A cat meows;
A dog barkles;
Let's revise our model by setting this in order.
public class Cat {
public bool HasHair { get { return true; } }
public int Legs { get { return 4; } }
public string Speaks { get { return "Meows"; } }
}
public class Dog {
public bool HasHair { get {return true; } }
public int Legs { get { return 4; } }
public string Speaks { get { return "Barkles"; } }
}
Now, to save you time and coding, what could we do? Generalize what both classes have in common? Alright! But how to make it so!?
public class Animal {
public bool HasHair { get { return true; } }
public int Legs { get { return 4; } }
public virtual string Speaks { get { return "Does a sound"; } }
}
// We can now inherit from Animal to write our Cat and Dog classes.
public class Cat : Animal {
public overrides string Speaks { get { return "Meows"; } }
}
public class Dog : Animal {
public overrides string Speaks { get { return "Barkles"; } }
}
And you can do:
Dog dog = new Dog();
dog.Legs; // Because Legs is an Animal property, and a Dog inherits from Animal, then Dog has a property called Legs, since it got it from his base class.
Now, we can do:
Animal pet = (Animal)(new Cat());
That said, you can typecast a Cat to an Animal, because it is an Animal! Now, you have to consider that your typecasted Cat will "do a sound", instead of "meowling", since by typecasting Cat to Animal, you're saying that you want to work with any Animal, as long as it is one. So both Cat and Dog are animals.
We could push our example even further by saying that not every animal has four legs, some doesn't have any, and others have only two. Then, we would have to generalize and to specialize accordingly.
In short: Yes
Like what was already said, One doesn't inherit from Two, so there's no "logical" default action to take here.
You should look into Conversion Operators. This'll let you still use the two=(Two) one syntax after defining an operator, like this(in the class def):
public static explicit operator Two(One o)
{
var t=new Two();
t.first=o.first;
t.second="default";//or whatever kind of default value you want
return t;
}
You can't cast a One as a Two because One does not inherit from Two. The other way around would work fine though (Two two = new One();)
In order to get a Two from a One you will have to create a new Two. You could have a method that copies all members of One to Two or you could have a constructor for Two that takes a One and sets the properties from there.
It is important to remember that one and two are just pointers in memory to an instance of an object.
If we were to write this out in plain English it would read something like this:
One one = new One();
Create a pointer in memory that refers
to an object of type One and label it
one, Then create an object of type One
and place it at the memory location
indicated by one.
two = (Two) one;
Replace the object referenced by two
with the object referenced by one, and
treat it as though it were an object
of type Two
Aside from the obvious typing problem you have, this will only replace the referenced object in memory, not copy the values from one to the other.
Yes, you have to implement a method that copies all members of one to two. Normally, you would make a constructor:
public Two(One one) {
this.first = one.first;
}
// Elsewhere ...
Two two = new Two(one);
Or if you want to copy over the values of an existing instance, you might do it with an instance method:
public void CopyValuesFrom(One one) {
this.first = one.first;
}
// Elsewhere ...
Two two = new Two();
two.CopyValuesFrom(one);
Related
Thanks ahead, community!
As the title describes, I would like to cast an object that is in parent type to a child type, which is actually a child type, whilst this 'specific type' cannot be known until runtime.
Lets say I have following data holder:
public class Holder {}
public class Holder<T> : Holder
{
public T Value;
}
And this Holder (not Holder<T>) will be given to some script at runtime.
I need to cast this Holder into Holder<T> (eg, Holder<string>), so that I can access the Value : T.
For now, I can just mannually add casting cases and their coresponding methods to process it, but time by time there will be more types that goes into this Holder<T>, and it would become imposible to manage in this way.
Is there a way to accomplish this objective?
This Holder must not be flattened, as it is being used in a context as below:
public class SomeNode
{
protected Holder holder;
}
public class SomeNode<T> : SomeNode
{
public SomeNode<T>()
{
holder = new Holder<T>();
}
}
I have no clue how to approach this, nor a search keyword to catch a hint about this.
Automatic suggestions came up before posting seems not my case, which were:
C# Create (or cast) objects of a specific type at runtime
C# Accessing generic Method without knowing specific type
Edit
Thanks to #W.F., I could start searching with an effective keyword 'dynamic object', and I ended up finding System.Reflection as my desired soultion.
It looks like as belows and currently it solves my immediate issue:
holder.GetType().GetProperty("GetValue").Invoke(holder, null);
But as pointed out by #OlivierJacot-Descombes, my structure and a way of using it is breaking a purpose of polymorphism. Therefore I still need a better solution, which would do a job I am looking for and also not breaking polymorphism.
Possible walkaround that comes in my head is that, first, create a method GetValue() in Holder, and also create class that inherits from Holder to implement this method:
public class Holder
{
public virtual string GetValue() => "";
}
public class Holder<T> : Holder
{
public T Value;
}
public class FloatHolder : Holder<float> //for example
{
public override string GetValue() => Value.ToString();
}
Second, change node structure like:
public class SomeNode
{
protected Holder holder;
}
public class SomeNode<T> : SomeNode {}
public class FloatNode : SomeNode<float>
{
public FloatNode()
{
holder = new FloatHolder();
}
}
Then, I can do like:
public class EchoNode : SomeNode
{
public void Tick()
{
Console.WriteLine(holder.GetValue());
}
}
Seems like too many classes are being created, but it also seems not breaking polymorphism.
Looking for further advices. Again, Thanks!
Edit#2
I already said this in the comment, but for better readability, I write this here as well.
Both Dynamic Object and System.Reflection were easy and fitting solutions which I was looking for, but they weren't best solutions in general.
At the beginning I was misinterpreting #OlivierJacot-Descombes 's answer. He was overall pointing out two impediments: first, my class structure is breaking polymorphism, and second, reflection is slow (and later I noticed, dynamic object as well). I didn't catch the last bit at first so I went through a long way.
Moreover, turned out, I couldn't use dynamic object for my project context, as I am not using normal C# but a Unity C#. Technically I can, but they don't blend well.
Thankfully, my revised solution was acceptable. Therefore I decided to select #OlivierJacot-Descombes 's post as an answer. But I hope, still, people would approach and leave me an good advices.
Thank you all.
If you need to cast to a specific type, you are doing polymorphism wrong. Of course you could do something like this:
switch (holder)
{
case Holder<string> stringHolder:
DoStringThing(stringHolder.Value);
break;
case Holder<int> intHolder:
DoIntThing(intHolder.Value);
break;
...
}
See also: Switch statements with patterns.
However, the idea behind polymorphism is to be able to do things without having to know the specific type. Therefore, re-design the holder classes and have them do the type specific thing themselves:
public abstract class Holder
{
public abstract void DoThing();
}
public abstract class Holder<T> : Holder
{
public abstract T Value { get; }
}
Some examples of specific types:
public class StringHolder : Holder<string>
{
public StringHolder(string value)
{
Value = value;
}
public override string Value { get; }
public override void DoThing()
{
Console.WriteLine($"String of length {Value.Length} is \"{Value}\"");
}
}
public class IntHolder : Holder<int>
{
public IntHolder(int value)
{
Value = value;
}
public override int Value { get; }
public override void DoThing()
{
Console.WriteLine($"The integer {Value} is {(Value % 2 == 0 ? "even" : "odd")}");
}
}
Now you can simply write
holder.DoThing();
... without having to cast.
Update
Your edited question indeed shows a polymorphic version.
Here I want to present another approach which merges Holder and Holder<T> in a single class through the use of interfaces.
public interface IHolder
{
object Value { get; set; }
}
public interface IHolder<T> : IHolder
{
new T Value { get; set; } // The new keyword hides the inherited property.
}
public class Holder<T> : IHolder<T>
{
object IHolder.Value
{
get => Value; // Returns T Holder<T>.Value as object.
set => Value = value is T t ? t : default; // Sets T Holder<T>.Value.
}
public T Value { get; set; }
}
Holder<T> now implements a "neutral" Value property declared in IHolder based on the object type. Since it implements it explicitly (i.e., instead of public object Value we write object IHolder.Value), this property is hidden, unless it is accessed through the interface. This allows you, for example, to declare a List<IHolder> and to retrieve different kinds of Holder<T> values with list[i].Value as object.
But you have a variable Holder<float> floatHolder, you can get the strongly typed float value.
Note that this still allows you do derive more specific types like class FloatHolder : Holder<float>, but it might not even be necessary.
If you intend to work only with derived types, you can mark Holder<T> as abstract and also all the members that must be implemented by the deriving classes. This makes it impossible to create an instance of Holder<T> with new and also allows you to declare abstract methods without body.
community! It's a good question. That was interesting.
I think this is simple solve for this question.
We just need to create a simple constructor like below
public class Holder
{
public string SomeData; // just example data
public Holder()
{
}
public Holder(Holder someData)
{
SomeData = someData.SomeData;
}
}
public class Holder<T> : Holder
{
public T Value;
public Holder(Holder a, T t = default)
:base(a)
{
Value = t;
}
}
public class Programm
{
void Main()
{
var h = new Holder();
var g = new Holder<string>(h);
}
}
I am trying to understand the logic behind some C# casting conditions for classes, This is my testing code
File: example.cs
public class Animal { public string animal_name = "Animal"; }
public class Dog : Animal { public string dog_name = "Dog"; }
public class Class1
{
public void createObjects()
{
var animal1 = new Animal();
printAnimalName(animal1);
}
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.dog_name);
}
}
In my Main function, I call the call createObjects function as follows:
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.createObjects();
Console.ReadLine();
}
Running the code above gives an error
System.NullReferenceException:'Object reference not set to an instance of an object'
I understand that this is the way it should be, due to the casting in:
var dog1 = my_animal as Dog;
But what is the logic behind it? Why can't we call the function printAnimalName by passing an Animal object for it? This should be possible as per my understanding, because the function expects an Animal object.
After that var dog1 = my_animal as Dog; // dog1 is of type Dog you need to add only null check:
if(dog1 != null)
{
Console.WriteLine(dog1.dog_name);
}
I think you need to learn about polymorphism, abscract classes and interfaces.
public abstract class FourLeggedAnimal
{
public int GetLegCount()
{
return 4;
}
}
public class Dog : FourLeggedAnimal
{
public string GetScientificName()
{
return "doggus scientificus";
}
}
public class Cat : FourLeggedAnimal
{
public string GetServant()
{
return "human";
}
}
public class AnimalInformer
{
public void DisplayInformation(FourLeggedAnimal animal)
{
Console.WriteLine("It has {0} legs", animal.GetLegCount());
if (animal is Dog)
Console.WriteLine("Its scientific name is {0}", ((Dog)animal).GetScientificName());
if (animal is Cat)
Console.WriteLine("Its servant is {0}", ((Cat)animal).GetServant());
}
}
Here you use the absract class to provide base functionality to all other classes derived from it. All classes derived from FourLeggedAnimal have a method GetLegCount() that returns the number of legs.
But a cat has a servant a dog doesnt have, it just has a friend(both humans, but different relations). So the dog needs no method "GetServant" but the cat does. -> Differenct implementations in 2 seperate classes
Another example with interfaces is that each derived class needs to provide that functionality.
public interface IMovableObject
{
int GetMaxSpeed();
}
public class Car : IMovableObject
{
public int GetMaxSpeed()
{
return 100;
}
}
public class Human : IMovableObject
{
public int GetMaxSpeed()
{
return 20;
}
}
public static class SpeedChecker
{
public static void CheckSpeed(IMovableObject speedster)
{
Console.WriteLine("Checking Speed..");
int speed = speedster.GetMaxSpeed();
if (speed > 50)
Console.WriteLine("It's really fast!");
else
Console.WriteLine("Just a turtle or something similar...");
}
}
Now, if you have a Method getting a IMovableObject that is actually a car, you call the implementation of Car:
Car c = new Car();
Human h = new Human();
Console.WriteLine("Checking Car..");
SpeedChecker.CheckSpeed(c);
Console.WriteLine("Checking Human..");
SpeedChecker.CheckSpeed(h);
-> returns:
Checking Car...
Checking Speed...
It's really fast!
Checking Human...
Checking Speed...
Just a turtle or something similar...
These are 2 uses where you derive classes and use castings to get certain functionality or use the basetype without casting but still getting different functionality
Your problem is here:
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.dog_name); //Animal does not have this property!
}
Casting does not invoke a constructor. This means that dog_name is null, as my_animal does not have a dog_name property. I think you missed something on inheritance here.
This is actually an example that happens in more complex form in the real world; Given class A, B inherits from A. Both have the same properties because of inheritance. Then someone makes a different property with a similar, but not congruous property name and uses it for the same function in the child object. Welcome to code smell city.
To fix your function so it comes across as a dog, you'd do two things:
public class Animal { public string animal_name = "Animal"; }
//since we want a different default, we can
//can make the change in the constructor
public class Dog : Animal
{
Dog(){ this.animal_name = "Dog"; }
//if you really, really want a second name string, you can do this:
public string Dog_Name
{
get { return this.animal_name; }
set { this.animal_name = value; }
}
}
Then, you need to make your method call the appropriate property.
public void printAnimalName(Animal my_animal)
{
var dog1 = my_animal as Dog; // dog1 is of type Dog
Console.WriteLine(dog1.animal_name);
}
I also recommend changing your public fields to properties and possibly override ToString() when all you want to do with an object is return a string representing it.
So I'm used to working with javascript, and being able to simply do
dog={};
dog.name="Rex";
dog.examine=function(){console.log("This is a dog. Its name is "+this.name+".");}
cat={};
cat.name="Phil Collins";
cat.examine=function(){console.log("This is a cat. Its name is "+this.name+".");}
dog.examine();
cat.examine();
This would return, of course : This is a dog. Its name is Rex. and This is a cat. Its name is Phil Collins.
I've started learning xna, and I'm very confused by this whole lambda/delegate/action system. I'm not sure what syntax to use, the compiler gets angry when I try to make a function with no input or output variables, and I'm having trouble keeping the proper scope for this. Could someone please help me find out how I'd port the above code into c#?
I made this a Community Wiki because this question is really too broad, C# and JavaScript are very different things and answer can't be complete. I'll just sketch a direction but the way to go is to learn C# and differences will be clear. That's the reason I'll try to first write something similar to JavaScript program you posted and then, step by step, to change it to be more C# style.
Let me also say that if you extensively want to use dynamic typing in C# (or JavaScript programming style) then (probably)...you picked wrong language.
Step 1
Something somehow close to what you write can be written in C# like this (let me use this example to highlight differences, you really have to buy a good C# book and start from there):
dynamic dog = new ExpandoObject();
dog.Name = "Pluto";
dog.Hello = new Action(() => Console.WriteLine("This is a dog named {0}", dog.Name));
dog.Hello();
First of all you see that in C# a variable must be typed, in this case with dynamic we bypass static typing and we may even change content later (but this is another story). ExpandoObject is a special object that can be expanded adding properties, it's not normal C# behavior where almost everything about types is checked at compile-times (don't think about casts, now).
Second line is pretty similar, nothing new (for you) here but pretty strange if you're a traditional C# programmer.
Finally the interesting part: we add a property that is a delegate (using a lambda) but here there is a big difference (you also noted by yourself): this has a different meaning in C# and within a method this is the instance of the object where method is declared (OK it's declared in the class but you know what I mean). Let's watch this: dog.Name, we captured dog variable inside our anonymous method (as you would do in JavaScript).
Step 2
It's just a starting point because design and philosophy is completely different, same thing in C# should be done with an Animal base class and Dog + Cat derived classes but you'll learn this by yourself. Let me do just one more simple step in that direction:
var typedDog = new {
Name = "Pluto",
Hello = new Action(() => Console.WriteLine("This is a dog named {0}", Name))
};
typedDog.Hello();
Maybe you don't see such big difference but this code is strongly typed! What does it means? We declared an anonymous class with two properties and one of them is a delegate, we still can't use this and in C# (unlike Java) we can't declare methods in anonymous types but now compiler knows (then it's compile-time) what things are. For example:
dog.Name = 2; // Valid, now Name is an integer
dog.Hello = 2; // Valid, also Hello is an integer
dog.Hello(); // This will fail at run-time because Hello now isn't a delegate
Is it bad, right? With our new typed object this isn't possible:
typedDog.Name = 2; // Compile-time error, Name is a string
typedDog.Hello = 2; // Compile-time error, Hello must be an Action delegate
Of course we can assign a new anonymous delegate to replace old one (but type must match):
typedDog.Hello = new Action(() => Console.WriteLine("This is a typed dog named {0}", typedDog.Name));
Step 3
This has been extensively described in other answers so I won't repeat, just to sketch things:
class Animal {
public string Name { get; set; }
public abstract void Hello();
}
class Dog : Animal {
public override void Hello() {
Console.WriteLine("This is a dog named {0}", this.Name);
}
}
Note that now you finally have this pointer and it does what you expect. It's used like this:
var dog = new Dog { Name = "Pluto" };
dog.Hello();
Note that in JavaScript you can even write this:
var anInteger = 2;
anInteger.PrintSomething();
That's not allowed in C# because at compile-time (unless you use dynamic variables) it needs to know if PrintSomething() is a method and how to call it. Same thing can be also done like this (using interfaces):
class IPolite {
void Hello();
}
class Dog : IPolite {
public string Name { get; set; }
public void Hello() {
Console.WriteLine("This is a dog named {0}", this.Name);
}
}
Now you can even have a completely different object:
class Car : IPolite {
public string Name { get; set; }
public void Hello() {
Console.WriteLine("This is a car, name is {0}", this.Name);
}
}
It can be used like this:
IPolite thing = new Dog { Name = "Pluto" };
thing.Hello();
thing = new Car { Name = "Ferrari F50" };
thing.Hello();
Please note we're reusing same thing variable. Many other things to see and to do...
In general C# and other strongly-typed languages are VASTLY different from script / run-time languages like JS. C# is a compiled language and this "strongly-typed" nature is ensured by the compiler. This is true for many type-safe (http://en.wikipedia.org/wiki/Type_safety) languages.
Generally speaking a class structure in C# would look like this:
public abstract class Animal {
//Fields or instance variables are typically hidden from the outside world (consuming code). This is controlled by the 'access-modifier' in this case, private.
private string _name;
//Constructor is called when you use the 'new' keyword to instantiate an instance of a type that derives from Animal (Animal cannot be instantiated directly because it is abstract).
protected Animal() {
//Avoids null references unless someone overrides the property setter, for this example, it's safe enough
_name = string.Empty;
}
//This is syntax for declaring a property
//properties are publicly accessible pieces of data that control access to a basic
// field (variable).
// It allows you to apply logic to the field it wraps.
// In this example, the field cannot be set to a null or empty string (except by the constructor, which bypasses the property.
public virtual string Name {
get {
return _name;
} set {
if(!String.IsNullOrWhiteSpace(value)) {
_name = value;
}
}
} // end property Name
//This is a method that must be overridden by any derived type that is not abstract and may (or may not) be overridden by a derived type that is abstract.
public abstract void Examine();
}
public class Cat : Animal {
public Cat : base() {}
public override void Examine() {
Console.WriteLine(String.Concat("This is a cat. It's name is ", this.Name, "."));
}
}
public Class Dog : Animal {
public Dog() : base() {}
public override void Examine() {
Console.WriteLine(String.Concat("This is a dog. It's name is ", this.Name, "."));
}
}
//In some runnable code elsewhere like a console application:
Animal cat = new Cat() {Name = "Mittens"};
Animal dog = new Dog() {Name = "Fido"};
cat.Examine();
dog.Examine();
For more information about access modifies, see here:http://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
You could use inheritance to accomplish it:
public class Animal
{
public string Name { get; private set; }
public Animal(string name)
{
this.Name = name;
}
public void Examine()
{
Console.WriteLine("This is a {0}. Its name is {1}.", this.GetType(), Name);
}
}
public void Dog : Animal
{
public Dog(string name) : base(name) { }
}
public void Cat : Animal
{
public Cat(string name) : base(name) { }
}
Then you can create instances of these derived types:
static class Main(string[] args)
{
Dog rex = new Dog("rex");
Cat phil = new Cat("Phil Collins");
rex.Examine();
phil.Examine();
}
Here's a simple example. I'd strongly suggest picking up a book or checking out a tutorial because this stuff will be covered pretty early on.
public abstract class Animal
{
public string Type { get; private set; }
public string Name { get; set; }
protected Animal(string type)
{
Type = type;
}
public virtual string Examine()
{
return string.Format("This is a {0}. Its name is {1}.", Type, Name);
}
}
public class Dog : Animal
{
public Dog() : base("Dog")
{
}
}
public class Cat : Animal
{
public Cat() : base("Cat")
{
}
}
var dog = new Dog { Name = "Rex" };
var cat = new Cat { Name = "Phil Collins" };
You can use the so-called anonymous functions or you could make this examine function of yours to be a property of type Action. For e.g., you could write:
Animal.cs:
public abstract class Animal
{
public string Name { get; set; }
public Action Examine { get; set;}
}
Dog.cs:
public class Dog : Animal
{
}
Cat.cs:
public class Cat : Animal
{
}
And then, somewhere where you could use this, you can say:
Dog dog = new Dog { Name = "Rex" };
dog.Examine = delegate
{
Console.WriteLine("This is a dog. Its name is {0}.", dog.Name);
};
Cat cat = new Cat { Name = "Phil Collins" };
cat.Examine = delegate
{
Console.WriteLine("This is a cat. Its name is {0}.", cat.Name);
};
dog.Examine();
cat.Examine();
Bear in mind that instead of using 'this', you're using a reference to the previously instantiated class which extends Animal (Dog or Cat).
There's also the other option... Combining ExpandoObject class and a dynamic keyword:
dynamic dog = new ExpandoObject();
dog.Name = "Rex";
Action examineDog = delegate {
Console.WriteLine("This is a dog. Its name is {0}.", dog.Name);
};
dog.Examine = examineDog;
dynamic cat = new ExpandoObject();
cat.Name = "Phil Collins";
Action examineCat = delegate
{
Console.WriteLine("This is a cat. Its name is {0}.", cat.Name);
};
cat.Examine = examineCat;
dog.Examine();
cat.Examine();
Suppose I have these codes (and the classes are in the same namespace):
class Animal
{
int numberOfLegs = 4; // initialized
public int returnNumberOfLegs()
{
return numberOfLegs;
}
}
class Snake
{
internal Animal myAnimalObject = new Animal();
myAnimalObject.numberOfLegs = 0; // why is this line not allowed?
}
class Program
{
public static void Main(string [] args)
{
Snake mySnakeObject = new Snake();
Console.WriteLine("Snake");
Console.WriteLine("Number of Legs: {0}", mySnakeObject.myAnimalObject.returnNumberOfLegs());
}
}
Observe the class Snake. When I place these 2 lines of code in Main(), it is possible/allowed and will work if I declare the variable numberOfLegs with the right access modifier. Why can't I do it in the class Snake itself? What should I do to allow it?
Note that the 2nd line of code from class Snake is invalid and these are the errors it produced:
1) Error 1 Invalid token '=' in class, struct, or interface member declaration
2) Error 2 'myNamespaceName.Snake.myAnimalObject' is a 'field' but is used like a 'type'
Thanks. I just want to learn about this.
Edit:
Okay, thanks guys. I know about constructors and inheritance, but somehow, I'm being forced to do it "the hard and not-so-smart" way, for learning purposes(?). And that I even had to set the default value to 4. Thank you for your replies. Plus, I just made up these classes.
Because executable code should be placed either in constructor or in some method/property.
You cannot place code just inside the class, put it in the constructor.
class Snake
{
internal Animal myAnimalObject = new Animal();
public Snake()
{
myAnimalObject.numberOfLegs = 0;
}
}
When you write
internal Animal myAnimalObject = new Animal();
in the class body, it's a kind of a syntax sugar; compiler will create constructor and put your code line inside it.
and it will look like
class Snake
{
internal Animal myAnimalObject;
public Snake()
{
myAnimalObject = new Animal();
myAnimalObject.numberOfLegs = 0;
}
}
First of all, you can't do this in the class initializer:
myAnimalObject.numberOfLegs = 0;
Since you're not setting a class member itself, but rather interacting with a class member, you'd have to do it in the constructor:
public Snake()
{
myAnimalObject.numberOfLegs = 0;
}
Also, in order to access numberOfLegs it would need to be internal or public:
internal int numberOfLegs = 4; // initialized
More to the point of the whole scenario however, this seems like a very odd abstraction. Though part of me applauds the use of composition instead of inheritance, this seems more like a case where inheritance is warranted. It seems that Animal really shouldn't be initializing any value for numberOfLegs by default. Indeed, Animal shouldn't even be a concrete object given the real-world concepts being modeled. Instead, I might try something like:
abstract class Animal
{
public abstract int NumberOfLegs { get; }
}
class Snake : Animal
{
public override int NumberOfLegs { get { return 0; } }
}
The idea being that a Snake is an Animal, that an Animal by itself can't exist unless it's a specific type of Animal, and that each individual type of Animal internally controls its own values and all the abstract Animal class does is define what those values need to be.
You should use inheritance instead. Make Animal an abstract class, base class for all animals. Composition (what you use now) does not make much sense in this case.
abstract class Animal
{
protected int numberOfLegs = 4; // default number of legs
public int NumberOfLegs { get { return numberOfLegs; } }
public Animal(int legs)
{
numberOfLegs = legs; // initialize number of legs
}
}
All concrete animals then derive from this class.
class Snake : Animal
{
public Snake() : base(0) // specify that number of legs is 0
{
}
}
The base(0) is a call to a base class constructor, so you are calling Animal(int legs) with an argument 0.
Do it like this:
abstract class Animal
{
private readonly int numberOfLegs;
protected Animal(int nrLegs = 4)
{
numberOfLegs = nrLegs;
}
public int returnNumberOfLegs()
{
return numberOfLegs;
}
}
class Snake : Animal
{
public Snake() : base(0)
{
}
}
I have a class called Star, and it has a
public List<Planet> Planets = new List<Planet>();
There is a method that creates the Planets with the variables needed, though I want some of the information about the star accessible in the planet class.
right now there are 4 variables I construct the 'Planet Class' with but I need about 6 of the variables from the 'Star Class' available in the 'Planet Class'.
Is there a way to have a reference to the parent star in the planet class? and how would I pass the reference to the Planet?
Thanks!
You can include a reference in the Planet class to the Star. You can then create a constructor that takes that reference, like so:
public class Planet
{
private Star orbits;
...
public Planet(Star orbits)
{
this.orbits = orbits;
...
}
...
}
You can then instantiate it from in Star like this:
public List<Planet> Planets = new List<Planet>(this);
There are plenty of ways to accomplish this, just one idea:
What about making a parameter for your contstructor like:
private List<Star> _solarSystem;
Planet(List<Star> solarSystem)
{
this._solarSystem = solarSystem;
}
From OO point of view it would be better to have instead of the list a class. I assume the code you have posted is also in some class, so how is your class called ?
private SolarSystem _solarSystem;
Planet(SolarSystem solarSystem)
{
this._solarSystem = solarSystem;
}
A typical solution is to inject an interface that the class implements into the dependent class (dependency injection). Something like this for your case:
internal interface IStar
{
void Method1();
string Property1 { get; }
...
}
internal abstract class Star : IStar
{
protected Star()
{
foreach(string planetName in planetNames)
{
Planet p = new Planet(planetName, this);
Planets.Add(p);
}
}
public void Method1()
{
...
}
public string Property1
{
get { return string.Empty; }
}
}
internal class Planet
{
string name;
IStar parentStar;
internal Planet(string name, IStar parentStar)
{
this.name = name;
this.parentStar = parentStar;
}
}
Doing it in this fashion allows you to pass in different classes that implement IStar if needed. Maybe you have the base abstract class Star, which is inherited by ClassAStar, DwarfStar, etc. The Planet doesn't care what kind of star you pass in, as long as it implements the IStar interface. This promotes loose coupling, making your code easier to maintain.
Use dictionary like this:
IDictionary<Star, IList<Planet>> planetSystems = new Dictionary<Star, IList<Planet>>();