I have a class "Animals" which contains instance variable name and a set method accordingly
public void setName(string newName)
{
name = newName;
}
I have other childclasses that inherits from "Animals"
I create an object from one of these and add it to my List< Animals > accordingly:
Turtle anAnimal = new Turtle();
//add to list
list.Add(anAnimal);
I assign properties in relation to every class like this:
//assigning all values
//bird info
foreach (var Animals in list.OfType<Birds>())
{
Animals.setFeatherColor(feather_color);
Animals.setWingspan(wingspan);
}
//reptile info
foreach (var Animals in list.OfType<Reptiles>())
{
Animals.setScalesColor(scales_color);
Animals.setVenemous(Venemous);
}
//animal info
foreach (var Animals in list.OfType<Animals>())
{
Animals.setId(list);
Animals.setAge(age);
Animals.setDiet(diet);
Animals.setGender(gender);
Animals.setName(name);
}
5.This is where the problem is:
Animals.setName(name) assigns the same value every time I create a new animal with different names
6.name comes from textbox.Text;
Why is this happening? thank you
(I am not forgetting to change textbox.Text)
Looks like there's a lot of code missing, yet my understanding is that you have a superclass called Animals and a series of derived classes Bird, Reptile and such... so when you call Animals.SetName(name) you're calling it within a foreach loop that won't actually filter anything, since all of your classes are derived from the Animals class.
public class Animal
{
public string name { get; set; }
}
public class Bird : Animal { }
public class Reptile : Animal { }
static void Main(string[] args)
{
List<Animal> animals= new List<Animal>();
Bird bird = new Bird();
bird.name = "bird";
Reptile reptile = new Reptile();
reptile.name = "reptile";
animals.Add(bird); animals.Add(reptile);
foreach (var animal in animals.OfType<Animal>())
{
Console.WriteLine(animal.name); // writes 'bird', 'reptile'
}
}
Related
I'm trying out C# for the first time, so I apologize if this has a simple solution or if the language simply does not allow it.
I'll simplify my problem to the best of my ability - Imagine I have the following classes:
public class Animal
{
public bool isAlive = true;
public List<Animal> friends;
}
public class Dog : Animal
{
public string Bark()
{
return "Woof!";
}
}
public class Cat : Animal
{
public bool hatesMe = true;
}
public class GoldenRetriever : Dog
{
public bool greatForFamilies = true;
}
Now, the following code:
var Chuck = new GoldenRetriever();
var Stripey = new Cat();
Chuck.friends.Add(Stripey);
var myVar1 = Stripey.hatesMe; //fine
var myVar2 = Chuck.friends[0].hatesMe; //error
I know that when I added Stripey to Chuck's friends list, Stripey was converted to an Animal and lost its Cat members - my problem is: how can I have a list/array/collection of different types, without them losing their specific members?
Thanks in advance!
Actually you are not losing any Data, while storing it in its base type. To access the given data, you need to convert it to the data type which inherits the base type. In your case you need to cast it to Cat in order to access the hatesMe field. This would look something like the code below.
var myVar2 = ((Cat)Chuck.friends[0]).hatesMe;
In simple words, when storing an object in a datatype which it implements or inherits, you are only hiding its other members.
Twenty is right. You need need cast the class Animal to Cat before you can access the 'hatesMe' field:
var myVar2 = ((Cat)Chuck.friends[0]).hatesMe;
But if the type of Animal is unknown you could work with virtual/override properties:
public class Animal
{
public bool isAlive = true;
public List<Animal> friends;
public virtual bool HatesMe
{
get
{
return false;
}
}
}
public class Dog : Animal
{
public string Bark()
{
return "Woof!";
}
}
public class Cat : Animal
{
public override bool HatesMe
{
get
{
return true;
}
}
}
public class GoldenRetriever : Dog
{
public bool greatForFamilies = true;
}
Now the property 'HatesMe' works with all classes which are inherited from Animal:
var Chuck = new GoldenRetriever();
var Stripey = new Cat();
Chuck.friends.Add(Stripey);
var myVar1 = Stripey.hatesMe; //fine
var myVar2 = Chuck.friends[0].HatesMe; //fine
In case the type of Animal is unknown but the given class structure shouldn't be touched you could access the 'hatesMe' field through reflection using the dynamic keyword:
dynamic Stripey = new Cat();
bool b = Stripey.hatesMe; //fine
Be aware, accessing fields through reflection is slow. Furthermore if you rename the 'hatesMe' field without adapting the dynamic code, the code will throw an exception.
I'm writing a class that will consume classes and create little reports of information. The problem is, even though they all inherit form a base class, these child classes don't have to implement all the sames methods and properties. Just the relevant ones...
I can't cast the classes because at design time I don't which ones will be used... We have a framework and on a job by job basis a developer takes it and implements some job specific code. They base class has some methods they have to implement (Init, Report, Audit) but then depending on what type of job it is, it will have one or two of a few properties and a method or two.
So (as my simplistic example below) they might implement Cat, but also need the 2nd class thats simliar to Cat, but different enough to warrant a new class, so create Cat2.
I know it sounds a weird of working, but whilst the the developers are using the framework, they are working with their instantiated classes.
class Animal
{
////common stuff
public
}
class Cat : Animal
{
public Name { get; set; }
public Speak()
{
Console.WriteLine("Meow");
}
}
class Dog: Animal
{
public Name { get; set; }
public Speak()
{
Console.WriteLine("Woof");
}
}
class Person: Animal
{
public Title{ get; set; }
public Name { get; set; }
public Speak()
{
Console.WriteLine("Hello");
}
}
class Spider: Animal
{
public Name { get; set; }
}
List<Animal> animals = new List<Animals> {
new Cat { Name = "Bob" },
new Dog { Name = "Fido" },
new Person { Name = "Harry", Title = "Mr" },
new Spider { Name = "Boris" }
}
foreach (Animal item in animals)
{
///now is wishful pseudo code...
if item has Speak then speak()
if item has Title then write Title
if item has Name then write Name
}
I just want to loop through the list, if it has a certain property then read it. If it has a certain method, then call it.
if it has a certain property then read it. If it has a certain method, then call it.
it sounds like each of those features define an interface, i.e.
interface IHazName { string Name {get;} }
interface IHazTitle { string Title {get;} }
interface ICanSpeak { void Speak(); }
...
foreach (Animal item in animals)
{
if (item is ICanSpeak cs) cs.Speak();
if (item is IHazTitle ht) Write(ht.Title);
if (item is IHazName hn) Write(hn.Name);
}
...
class Cat : Animal, IHazName, ICanSpeak
{...}
class Dog : Animal, IHazName, ICanSpeak
{...}
class Person : Animal, IHazName, IHazTitle, ICanSpeak
{...}
class Spider : Animal, IHazName
{...}
One particularly nice thing about using interfaces is that you can fudge the names a bit:
class Dog : Animal, IHazName, ICanSpeak
{
//...
public void Bark() { Say("woof"); } // method is called Bark on the public API
void ICanSpeak.Speak() => Bark(); // but Speak on the ICanSpeak API
}
Note: the usage here:
if (item is ICanSpeak cs) cs.Speak();
requires a modern C# compiler; if you're using an older compiler, then:
if (item is ICanSpeak) ((ICanSpeak)item).Speak();
or:
var cs = item as ICanSpeak;
if (cs != null) cs.Speak();
Likewise,
void ICanSpeak.Speak() => Bark();
is the same as, on older compilers,
void ICanSpeak.Speak() { Bark(); }
You can add a new abstract method, then implement it in child classes.
class Animal
{
abstract Work();
}
class Cat : Animal
{
public Name;
public Speak();
override Work()
{
Speak();
Write Name;
}
}
class Person: Animal
{
public Title;
public Name;
public Speak();
override Work()
{
Speak();
Write Title;
Write Name;
}
}
foreach (Animal item in animals)
{
item.Work();
}
I have an Abstract class Animal, which stores some common fields, e.g name, health. I have a number of animal classes e.g Tiger, but I also have a class Fish which has an additional field the other animal classes don't have, canSplash.
I then have a list of Animal objects. I can access the common fields, but I cannot access the canSplash field for Fish. I am looking for help to accessing a concrete classes specific fields from an Abstract Class.
class Zoo
{
public List<Animal> animals = new List<Animal>();
public Zoo()
{
animals.Add(new Monkey());
animals.Add(new Tiger());
animals.Add(new Fish());
}
public static void displayZooPopulation()
{
foreach (var a in animals)
{
if (a.species == "fish" && a.CanSplash)
{
Console.WriteLine("{0} can splash",a.Name);
}
}
}
}
class Fish : Animal {
private bool canSplash
public bool CanSplash { get; set; }
}
Simple answer would be, check the type by safely cast to it and check if it is not null:
var fish = a as Fish;
if (fish != null && fish.CanSplash)
{
Console.WriteLine("{0} can splash",a.Name);
}
This is perfectly okay if you only have one child class which has this specific behavior.
But consider you have other child classes of animals which also are able to splash, like let's say an elephant, then you have to check for the elephant's class also if you want to find all animals in your zoo which can splash.
A better approach is to use an interface for such things like ISplashable:
public interface ISplashable
{
bool CanSplash { get; }
}
Now implement this interface in all of your child classes which should be able to splash:
public class Fish : Animal, ISplashable
{
// ...
public bool CanSplash { get; set; } // this also implements CanSplash { get; }
// ...
}
public class Elephant : Animal, ISplashable
{
// ...
public bool CanSplash { get { return true; } }
// ...
}
Now you can check against that interface instead of the concrete class:
var splasher = a as ISplashable;
if (splasher != null && splasher.CanSplash)
{
Console.WriteLine("{0} can splash",a.Name);
}
//remove the static keyword, for you can't access animals (or animals should be static)
check type of a , and take your action
The method can be:
public void displayZooPopulation()
{
foreach (var a in animals)
{
if ( a is Fish)
{
//here sure "a" is not null, no need to check against null
var fish = a as Fish;
// if (a.species == "fish" && (Fish) a.CanSplash)
if ( fish.CanSplash)
{
Console.WriteLine("{0} can splash", a.Name);
}
}
}
}
BTW, you say that Animal is abstract class , where is implementation of abstract methods in Fish class :)
This question already has answers here:
Convert List<DerivedClass> to List<BaseClass>
(13 answers)
Closed 8 years ago.
In the below example, I can add have a List of type Animal. Since Dog and Cat derive from animal, the List can hold each. However, if I have a method that accepts List<Animal>, you can not pass in a reference List<Dog>. If Dog is derived from animal, why is this not valid? However if i have a method that excepts a parameter of type Object, and all objects derive from Object, it works.
class Program
{
static void Main(string[] args)
{
List<Animal> animals = new List<Animal>();
animals.Add(new Dog() { Color = "Black" }); // allowed since Dog derives from Animal
List<Dog> dogs = new List<Dog>();
dogs.Add(new Dog() { Color = "White" });
Test(animals);
Test(dogs); // not allowed - does not compile
Test2(dogs); // valid as all objects derive from object
}
static void Test(List<Animal> animals) {
// do something
}
static void Test2(object obj) {
}
}
public class Animal {
public String Color { get; set; }
}
public class Dog : Animal { }
public class Cat : Animal { }
Imagine that Test(dogs) did compile. Then imagine that Test() is implemented like follows:
static void Test(List<Animal> animals)
{
animals.Add(new Cat()); // Where Cat is derived from Animal
}
You've just added a cat to a list of dogs... Clearly that can't be allowed. And that's why it's not.
However, if you are only accessing the elements of the list rather than adding to the list, you can declare Test() like so:
static void Test(IEnumerable<Animal> animals)
{
foreach (var animal in animals)
{
// Do something with animal.
}
}
Then you can pass any collection type which implements IEnumerable<T>, such as List<T> and plain arrays.
Call Test(dogs.Cast<Animal>().ToList()). Change parameter type to IEnumerable to skip ToList() which creates a copy.
int is an object. List<Animal> is an object, as is List<Dog>. But List<Dog> is NOT List<Animal>.
i have a List<animal> where i want to add all animal their even i can add them or add them whole list.
how i can do something that they allow to add the List<rat> or rat their is not only one i need to add any type of animal in it.
means i can allow both
List<animal> animal = new List<animal>();
animal.Add(new rat());
animal.Add(new List<Elephant>());
i need a thing more that all animal is all animal found in animal list. i not need to count all object i need to count Every animal who add seprately or add whole list.
Can someone explain the code in C#.
List<animal> animal = new List<animal>();
animal.Add(new Animal());
animal.AddRange(new List<animal>());
Of course if the types you are willing to add don't have a common base parent you cannot use a generic list. You might use an ArrayList which allows for storing any types.
UPDATE:
If Rat and Elephant both derive from Animal you can always do
List<animal> animal = new List<animal>();
animal.Add(new Rat());
And in .NET 4.0 thanks to generic covariance you can also do:
animal.AddRange(new List<Elephant>());
but not in previous versions of the framework.
For your example with two different kinds of animals, I think a base class of animal makes sense, and derive a separate class for Elephant and Animal. A less novel approach, though doable is creating a generic list of objects. Not sure what your project is, so depending on the situation, you'll need to choose the implementation to use. Add each object to the generic list and check the type before using it with GetType() method.
Here's an example of using derived class though. You could change the base class to be an interface or abstract class as discussed above. I'll provide an example shortly for using generic objects.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Using derived way.
List<Animal> animals = new List<Animal>();
animals.Add(new Rat("the rat's name"));
animals.Add(new Elephant("the elephant's name"));
foreach (Animal a in animals)
{
Console.WriteLine(
string.Format("Name of animal: {0}"), a.Name));
}
}
}
public class Animal
{
public Animal(string name)
{
this.Name = name;
}
public string Name
{
get;
private set;
}
}
public class Elephant : Animal
{
public Elephant(string name)
:base(name)
{
}
public string AnimalProps
{
get;
set;
}
}
public class Rat :Animal
{
public Rat(string name)
:base(name)
{
}
public string RatProps
{
get;
set;
}
}
Here's an example with using a list of objects. I'd advise against this implementation, as generally a base/abstract/interface class and derived classes is cleaner, though I have seen cases where something like this is required.
public Form2()
{
InitializeComponent();
List<object> objects = new List<object>();
objects.Add(new Rat("the rat's name"));
objects.Add(new Elephant("the elephant's name"));
foreach (object o in objects)
{
if(o.GetType() == typeof(Rat))
{
Rat r = o as Rat;
Console.WriteLine(
string.Format("Name of rat: {0}", r.Name));
}
else if(o.GetType() == typeof(Elephant))
{
Elephant e = o as Elephant;
Console.WriteLine(
string.Format("Name of elephant: {0}", e.Name));
}
}
}
public class Elephant
{
public Elephant(string name)
{
this.Name = name;
}
public string Name
{
get;
private set;
}
public string AnimalProps
{
get;
set;
}
}
public class Rat
{
public Rat (string name)
{
this.Name = name;
}
public string Name
{
get;
private set;
}
public string RatProps
{
get;
set;
}
}