It might be a silly question, but i'm new to C#. I am wondering if there is a way to use directly parent's attributes in child class. I did a lot of Eiffel and when a class is inherited by one or more classes(cause yes Eiffel don't have interfaces you can inherit multiple classes).
Just like that exemple:(Eiffel langage)
Parent Class:
class Parent
features
int id
string lastName
Child Class:
class Child inherit
PARENT
feature
bool isChild
In that case, Child class already got access to id and lastName and can be set directly as part of Child attributes, don't have to create a Parent.
But so far i made this(C# langage):
Parent class:
public class Character
{
Int32 Id;
String name;
List<String> images;
public Character()
{
name = "";
images = null;
}
public Character(string a_name, List<String> imagePaths)
{
name = a_name;
images = imagePaths;
}
public Character(Int32 a_id, string a_name, List<String> imagePaths)
{
Id = a_id;
name = a_name;
images = imagePaths;
}
}
Child class:
public class NPC : Character
{
public bool isVender;
public NPC()
{
Character character = new Character();
isVender = false;
}
public NPC(string a_name, List<String> images)
{
Character caracter = new Character(a_name, images);
isVender = false;
}
public NPC(string a_name, List<string> images, bool a_bool)
{
Character caracter = new Character(a_name, images);
isVender = a_bool;
}
}
So there is my question, is there a way to get acces directly to parent's attributes in C# just like Eiffel?
Declare the fields you want to use in child classes as protected. Learn more about protected visibility modifier here.
public class Character
{
protected Int32 Id;
protected String name;
protected List<String> images;
public Character()
{
name = "";
images = null;
}
public Character(string a_name, List<String> imagePaths)
{
name = a_name;
images = imagePaths;
}
public Character(Int32 a_id, string a_name, List<String> imagePaths)
{
Id = a_id;
name = a_name;
images = imagePaths;
}
}
Then you can use the protected fields in child classes.
What you really seem to want is to use the base class's constructor to set the base class's fields, which is a slightly different syntax in C#:
public class NPC : Character
{
public bool isVender;
public NPC() : base()
{
isVender = false;
}
public NPC(string a_name, List<String> images) : base(a_name, images)
{
isVender = false;
}
public NPC(string a_name, List<string> images, bool a_bool) : base(a_name, images)
{
isVender = a_bool;
}
}
is there a way to get acces directly to parent's attributes in C# just like Eiffel?
If you do not specify an accessibility for a class member, they are private by default, which means that they are only accessible within the class itself. So the simplest change is to make them protected.
public class Character
{
protected Int32 Id;
protected String name;
protected List<String> images;
A better solution may be to add protected properties on top of the fields, which will still protect the actual fields but allow inherited classes to change the behavior of the properties.
Related
I have been facing a challenge, questioning my faith in OOP. Kindly let me know how if this is possible:
I have a parent class with a Static List (to keep track of all objects created, mainly for UI DataGrid reasons) and a Method referring to that List. Something like that
abstract class Animal
{
public static List<Animal> objList;
public String Name;
public Animal(String Name)
{
this.Name = Name;
objList.Add(this);
}
public virtual void delete(int i)
{
objList.RemoveAt(i);
}
now I have a child class with also a static list (same name same purpose just different class) but in order to have the method referring to the child.list I have to rewrite the method. like that
class Cat : Animal
{
public static List<Cat> objList;
public Cat(String Name) : base(Name)
{
}
//whould it be possible to ommit this method?
public override void delete(int i)
{
objList.RemoveAt(i);
}
}
This cannot be the best way. If I would have 5 children they would all have the same part of code copy pasted.
There must be a way that the parent class "delete" method, if called from a child object, it deletes from the child list, not from the parent list.
Static properties and methods don't lend themselves to being overridden in an OOP manner, though they can be shadowed.
public class Parent : IDisposable
{
private static List<Parent> objList = new List<Parent>();
private static IReadOnlyList<Parent> readOnlyList = new ReadOnlyCollection<Parent>(objList);
public static IEnumerable<Parent> Instances { get { return readOnlyList; } }
private bool _isDisposed = false;
public bool IsDisposed { get { return _isDisposed; } }
public Parent()
{
objList.Add(this);
}
public void Dispose()
{
OnDispose(true);
GC.SuppressFinalize(this);
}
protected virtual void OnDispose(bool disposing)
{
if(disposing) { objList.Remove(this); }
_isDisposed = true;
}
}
public class Child : Parent
{
private static IEnumerable<Child> _instances = Parent.Instances.OfType<Child>();
public new static IEnumerable<Child> Instances { get { return _instances; }}
public Child() : base()
{
}
}
Now if you want to remove the ith item from the list, just use use Parent.Instances(i).Dispose();
You can also remove the ith Child instance by doing Child.Instances(i).Dispose()
Edit: Finalizer removed from Parent as suggested in the comments below.
Edit2: Simplified the LINQ expression in the Child class to use .OfType() as suggested in the comments.
The collection does not belong in the base class, and certainly, it does not belong in any derived classes.
Unfortunately, you do not show how your List<Animal> is used so it is difficult to show a meaningful answer without inferring behavior you might not desire.
But if you insist, you need to have one collection only to hold all the animals and to declare a static property that filters the original collection according to the type in each subclass.
public abstract class Animal
{
// this is the _only_ field that should contain
// a list of all the animals.
protected static readonly List<Animal> animals = new List<Animal>();
// Expose a read-only wrapper as public
public static IReadOnlyList<Animal> AllAnimals => animals.AsReadOnly();
protected Animal(string color)
{
animals.Add(this);
this.Color = color;
}
public string Color { get; }
public void RemoveMe()
{
int index = animals.IndexOf(this);
if (index >= 0)
{
animals.RemoveAt(index);
}
}
}
public class Cat : Animal
{
public static IReadOnlyList<Cat> AllCats => animals.OfType<Cat>().ToList().AsReadOnly();
public Cat(string name, string color) : base(color)
{
this.Name = name;
}
public string Name { get; }
}
public class Fish : Animal
{
public static IReadOnlyList<Fish> AllFish => animals.OfType<Fish>().ToList().AsReadOnly();
public Fish(string color) : base(color)
{
}
}
static class Program
{
static void Main(string[] args)
{
var cat1 = new Cat("Whiskers", "Tabby");
var fish1 = new Fish("Striped");
var cat2 = new Cat("Snoflake", "White");
var cat3 = new Cat("Midnight", "Black");
cat2.RemoveMe();
// list all remaining cats below
foreach (var cat in Cat.AllCats)
{
Debug.WriteLine($"{cat.Name} is a {cat.Color} cat.");
}
// Result in Output:
//Whiskers is a Tabby cat.
//Midnight is a Black cat.
}
}
Is there an access modifier, or combination thereof, to restrict access to an outer class only?
For the Position property of nested class PanelFragment below, I would like only the containing class ViewPagerPanels to be able to set it (via the setter, I realize this could be done through a constructor parameter also).
public class ParcelView : MXActivityView<ParcelVM>, ViewPager.IOnPageChangeListener, IFragmentToViewPagerEvent
{
private ViewPagerPanels _pagerPanels;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
_pagerPanels = new ViewPagerPanels(5); // 5: magic number, put int constant
_pagerPanels[0] = new ViewPagerPanels.PanelFragment(typeof(ViewA));
// ...
}
private class ViewPagerPanels
{
public class PanelFragment
{
public Fragment Fragment { get; set; }
// ?? - access modifer for set
public int Position { get; private set; }
}
public readonly int PANEL_COUNT;
private PanelFragment[] _panels;
public ViewPagerPanels(int count)
{
PANEL_COUNT = count;
_panels = new PanelFragment[PANEL_COUNT];
}
public PanelFragment this[int i]
{
get
{
return _panels[i];
}
set
{
_panels[i] = value;
// !! - cannot access private property
_panels[i].Position = i;
}
}
}
}
No, it's not possible to do it directly. The most restrictive access modifier, private, already allows access from within the same class. Every other modifier further expands that access.
Every class, no matter if its nested, private or public, always has access to every single of its own declared members, with no chance of applyng restrictions to itself. The closest we can get is by using a readonly field (or a getter only property) that prevents the declaring class from modifying a variable outside the constructor. But for a read-write one, we're out of options.
There is a solution for this type of protection scenarios. But you should do the following changes;
1- Replace you concrete class with an interface or abstract class and expose this to outside world
2- Implement this interface with a concrete class
3- Control the creation of this class by a factory method
4- Set the property by casting the interface (or abstract class) to your private class type
Sample code changes
public interface IPanelFragment
{
Fragment Fragment { get; set; }
// ?? - access modifer for set
int Position { get; }
}
class PanelFragment : IPanelFragment
{
public Fragment Fragment { get; set; }
// ?? - access modifer for set
public int Position { get; set; }
}
private IPanelFragment[] _panels;
public IPanelFragment CreateFragment(Fragment fragment, int pos)
{
return new PanelFragment() { Fragment= fragment, Position = pos };
}
public IPanelFragment this[int i]
{
get
{
return _panels[i];
}
set
{
_panels[i] = value;
// !! - cannot access private property
((PanelFragment)_panels[i]).Position = i;
}
}
A possible workaround
public int Position { get; private set; }
public int InitPosition { set { Position = value; } }
or, depending on your philosophical perspective concerning getter-less Properties
public void InitPosition(int value) { Position = value; }
I have 2 classes StaggingAttorney and Attorney. I will use the StaggingAttorney to collect information about an attorney and once I have all the information I will use it to create an Attorney profile using the best results. The 2 classes look like this;
private class StaggingAttorney : CourtCase.Attorney
{
public bool scraping = false;
public bool scraped = false;
public string caseNumber;
public CourtCase.Attorney toAttorney()
{
CourtCase.Attorney attorney = new CourtCase.Attorney();
return attorney;
}
}
...and...
public class Attorney
{
public string names;
public string matchString;
...
public List<Identity> IdentityMatches = new List<Identity>();
public List<Identity> getIdentityMatches()
{
return IdentityMatches;
}
public class Identity
{
public string names;
public string barNumber;
public string email;
public string phoneNumber { get; internal set; }
public object faxNumber { get; internal set; }
}
}
I have created a method called CourtCase.Attorney toAttorney() which you can see above. In this method I want to return a new CourtCase.Attorney with all CourtCase.Attorney inherited properties in the the StaggingAttorney
As #derloopkat suggested, you can simply cast your "StaggingAttorney" instance to his parent class. ("Attorney" in this case)
But if you really need a new instance of an "Attorney" with the same values than the parent "StaggingAttorney" just access to the parent fields of your "StaggingAttorney" object.
private class StaggingAttorney : CourtCase.Attorney
{
public bool scraping = false;
public bool scraped = false;
public string caseNumber;
public CourtCase.Attorney toAttorney()
{
CourtCase.Attorney attorney = new CourtCase.Attorney()
{
names = this.names,
matchString = this.matchString,
[... Initialize the other properties ...]
};
return attorney;
}
}
When you create an instance of a child class you are also creating the parent. So there are no many scenarios where you need to make another new instance from a child.ToParent() method. Having a conversion method like this makes more sense when one class is not inheriting from the other.
var attorney = new StaggingAttorney() { scraped = false };
attorney.names = "John"; //During the scraping process
attorney.scraped = true;
CourtCase.Attorney court = (CourtCase.Attorney)attorney; //casting
Console.WriteLine(court.names); //returns "John"
No need to copy data, because the child inherited names from its parent.
I'm currently working on a very simple Pokémon application in C#. I was uncertain on how to set up the relationship between the Pokémon and their fighting type but I just ended up doing the following:
abstract class Pokemon
{
private int number;
private string name;
protected string weakness;
protected string strength;
public Pokemon(int number, string name)
{
this.number = number;
this.name = name;
weakness = "none";
strength = "none";
}
}
I then made seperate classes that inherit Pokemon only to change the specific weakness and strength of the type.
class Fire : Pokemon
{
public Fire(int number, string name) : base(number, name)
{
weakness = "Water";
strength = "Grass";
}
}
Is it bad etiquette to create subclasses with the sole purpose of simply changing some of the initial values of the parent?
From here on, I just intend on doing the following when "creating" Pokémon for the application
pokemon = new Pokemon[6];
pokemon[0] = new Grass(001, "Bulbasaur");
pokemon[1] = new Grass(002, "Ivysaur");
pokemon[2] = new Grass(003, "Venusaur");
pokemon[3] = new Fire(004, "Charmander");
pokemon[4] = new Fire(005, "Charmeleon");
pokemon[5] = new Fire(006, "Charizard");
Any and all advice on how to improve the application or how to use inheritance properly is much appreciated :)
The inheritance looks OK but you may do some improvements. First, you don't need to define protected fields for weakness and strength, use protected properties instead. Second, using string type for weakness/strength doesn't seem to be the best choice. I would go with an Enum type.
enum PokemonComponent {
Water,
Grass
}
abstract class Pokemon
{
private int number;
private string name;
protected Pokemon(int number, string name)
{
this.number = number;
this.name = name;
}
protected abstract PokemonComponent Weakness {
get;
}
protected abstract PokemonComponent Strength {
get;
}
}
class Fire : Pokemon
{
public Fire(int number, string name) : base(number, name)
{
}
protected override PokemonComponent Weakness {
get {
return PokemonComponent.Water;
}
}
protected override PokemonComponent Strength {
get {
return PokemonComponent.Grass;
}
}
}
Is it somehow possible that base class can access fields in inherited class (has-a relationship)?
class BasicClass
{
public InheritedClass objTemp = new InheritedClass();
public BasicClass()
{
//Now i want to get some information from objTemp fields.
//But Name is protected, what should I do here?
objTemp.Name.Length();
}
}
class InheritedClass
{
protected string Name;
}
Maybe there are some tricky things that I don't know how to manage, or maybe it is better to create some more clever class hierarchy. Anyway thank you in advance.
Sorry for missunderstanding.In few words i have class Game which consist another class WordsContainer.
class Game
{
private Player objGamer;
private WordsContainer objWordsClass = new WordsContainer();
public Game()
{
Console.Title = "Hangman";
Console.Write("Player name information:");
string localName = Console.ReadLine();
objGamer = new Player(localName);
StringBuilder bumpWord = new StringBuilder(objWordsClass.getKeyWord().Length);
}
class WordsContainer
{
/// <summary>
/// WordsContainer class contains a list of strings from wich with getKeyWord method
/// we could get string type key.
/// </summary>
private List<string> wordBank = new List<string>() {"stack","queue","heap","git","array"};
public WordsContainer(){}
public string getKeyWord()
{
Random random = new Random((int)DateTime.Now.Ticks);
return wordBank[random.Next(0, wordBank.Count)];
}
So is it possible in this way somehow hide public string getKeyWord().
If you want to keep going on the code you have now, you could just define a public string GetName() function in InheritedClass and call it from the object that you create in the BasicClass
class BasicClass
{
public InheritedClass objTemp = new InheritedClass();
public BasicClass()
{
int nameLength = objTemp.GetName().Length();
}
}
class InheritedClass
{
protected string Name;
public string GetName()
{
return Name;
}
}