I have an abstract class called BaseMonster. This "base" class holds several values, such as float dyingTime =2, that will be the same for all monster subclasses. But since there are a lot of values like this, I didn't want to pass them into the object call when you "new" a monster.
So my question is: for subclass Ghoul, which inherits from BaseMonster, how can I pull the value for dyingTime from BaseMonster?
EDIT: To clarify, I need to have these values in Ghoul in order to run certain movement calculations that are different than the regular BaseMonster.
You should study the concepts of inheritance (BaseMonster being a base class for Ghoul) and access modifiers which govern which fields, methods and property are accessible from where.
You can find all access modifiers here
Also see this simple example:
public class Base
{
private float a;
protected float b;
public float c;
}
public class Sub : Base
{
public void DoSomething()
{
float x = base.a; // Error cannot access private member a
// Note that putting base before b and c here is optional
// though it does help with naming conflicts
// if Sub would also have a member b you could differentiate the two
// using this.b and base.b
float y = base.b; // Works
float z = base.c; // Works
}
}
Related
I've been learning C# the past couple of months and we've been tasked with a small project where there's this specific requirement:
We need to design the UI part of the project in such way, that we can figure out some random class fields and then get the input from a user to initialize those fields.
For example, in one run of the program we have this class A that has two integer fields.
In the UI section, we need to figure out class A has two integers, then we need to receive 2 integers from the user and pass them back for initialization.
Another scenario:
We have class B that has a boolean and an Enum field, and we need to do the same.
I've been leaning towards using reflection to gather the data needed in runtime, but I'm having a lot of problem figuring out how to actually receive the required input from user.
Another hurdle is that we were told that reflection isn't gonna help us and/or not required to fulfill this task.
I'm fairly inexperienced with the language so I assume there may be some other ways to implement this that I'm not aware of, but conceptually speaking - I really can't grasp how it is possible.
Here's some basic classes hierarchy to give a better example:
public abstract class Shape
{
private Point location;
private string color;
}
public abstract class NonCircular : Shape
{
private int edgesNumber;
}
public class Circle : Shape
{
private float radius;
private float diameter;
}
public class Triangle : NonCircular
{
public enum AngleType { Right, Acute, Obtuse }
public enum EdgePropery { Equilateral, Isosceles, Scalene }
private AngleType angleType;
private EdgePropery edgePropery;
private float angle1, angle2, angle3;
}
Going with this example - let's say that class 'Triangle' is being added to the solution later-on, after the project is done.
We first construct the abstract class 'Shape' with some of the basic fields that are shared among everyone, and then according to the requirements, the UI needs to receive the fields:
angleType, edgePropery, and angles1-3
and pass back values to the logical part of the project in order to initialize them properly.
You could add a method to the base class that returns information on the fields that need to be initialized. Each shape then overrides this method and returns its respective fields.
A second method is needed to actually initialize the fields after the UI got to know the required fields and had the user enter the values.
The main problem then is that a subclass does not know about any private fields in its base class and can not initialize them. This can be solved by always calling the base implementation of GetFieldInfo() and InitFields() in every override.
To ensure the collection of provided values is "consumed" correctly you could use a stack. Every base class will Pop() as many values from the collection it needs to initialize itself and then leaves the rest to its derived classes.
The same principle is used when accumulating all the fields from base classes and derived classes with GetFieldInfo().
Of course all this only works if the UI creates the Stack of values correctly, i.e. it must respect the order and Types it got via GetFieldInfo().
public abstract class Shape {
private Point location;
private string color;
public virtual IEnumerable<Type> GetFieldInfo() {
yield return location.GetType();
yield return color.GetType();
}
public virtual void InitFields(Stack<object> values) {
location = (Point)values.Pop();
color = (string)values.Pop();
}
}
public abstract class NonCircular : Shape {
private int edgesNumber;
public override IEnumerable<Type> GetFieldInfo() => base
.GetFieldInfo()
.Append(edgesNumber.GetType());
public override void InitFields(Stack<object> values) {
base.InitFields(values);
edgesNumber = (int)values.Pop();
}
}
public class Circle : Shape {
private float radius;
private float diameter;
public override IEnumerable<Type> GetFieldInfo() => base
.GetFieldInfo()
.Append(radius.GetType())
.Append(diameter.GetType());
public override void InitFields(Stack<object> values) {
base.InitFields(values);
radius = (float)values.Pop();
diameter = (float)values.Pop();
}
}
public class Triangle : NonCircular {
public enum AngleType { Right, Acute, Obtuse }
public enum EdgePropery { Equilateral, Isosceles, Scalene }
private AngleType angleType;
private EdgePropery edgePropery;
private float angle1, angle2, angle3;
public override IEnumerable<Type> GetFieldInfo() => base
.GetFieldInfo()
.Append(angleType.GetType())
.Append(edgePropery.GetType())
.Append(angle1.GetType())
.Append(angle2.GetType())
.Append(angle3.GetType());
public override void InitFields(Stack<object> values) {
base.InitFields(values);
angleType = (AngleType)values.Pop();
edgePropery = (EdgePropery)values.Pop();
angle1 = (float)values.Pop();
angle2 = (float)values.Pop();
angle3 = (float)values.Pop();
}
}
It just occured to me that using GetType() might count as reflection. But GetFieldInfo() could also return an IEnumerable<object> created from the field values directly. The UI could then use the is operator to check the field type and show the appropriate UI element (text box, number box, drop down etc).
By the way, I think this is a rather ugly solution. The back-and-forth between the base and sub classes makes for highly unreadable code. In a real-world application I'd probably rather take the performance hit of using reflection in favor of having the type inspection and initialization logic in one place. In the above solution this logic is spread all over your model classes.
class Program
{
static void Main(string[] args)
{
BaseC instance = new DerivedC();
// I don't see Y here.
Console.ReadLine();
}
}
public class BaseC
{
public int x;
}
public class DerivedC : BaseC
{
public int y;
}
I'm talking about the first line in the Main function. When I create it like this: DerivedC instance = new DerivedC(); everything's clear for me, and I see both variables, but why don't I see Y when creating an object that way above? How does the type of the 'instance' variable (either BaseC or DerivedC) affect the result?
That's the way polymorphism works in C#: in a variable of a base class type, you are allowed to store a reference to an instance of any subclass - but if you choose to do that, you can only "see" the base class members through the variable. The reason for this is safety: it is guaranteed that no matter what the variable refers to, it will have an x. However, there might exist other subclasses that do not have a y.
You might argue that it's obvious that the variable refers to an DerivedC, but that's just because this is a simple example. Imagine some code where there is a function that takes a BaseC as a parameter. The function might be called in one place with a DerivedC, and in another place with a DifferentDerivedC that doesn't have a y. Then, the function would fail in the second call if it were allowed to access y.
Because the type of instance is BaseC, it will not expose Property y.
To access Property y, you will need to do like below:
((DerivedC)instance).y
y is an extended property which is accessible only from the Child Class. That is the concept of Inheritence. The Child inherits the properties on child, not the other way round.
I'm a C++ developer learning C#, and I'm in a situation where I need a class C to have two members that belong to it that represent "robots." The robots need to be able to access private members of C, and they don't need to be used anywhere else. In C++ I'd use the "friend" keyword, but I don't know what to do here. I thought about doing something like this:
class C
{
private Member mem;
private Robot bot;
private class Robot
{
C owner;
public void function() { //Robot needs to use owner.mem here,
//but can't because it's private}
};
}
The trouble is that I don't know how to say that a Robot is "owned" by an instance of C, and can access its members.
One way to do it is to pass the outer class's instance to the inner class's constructor as a reference.
class C
{
private Member mem;
private Robot bot;
private class Robot
{
C owner;
public Robot(C c) {owner = c;}
public void function()
{
// Robot can use owner.mem here
}
};
}
There's no direct equivalent of friend - the closest that's available (and it isn't very close) is InternalsVisibleToAttribute but it breaks the relationships between classes and undermines some fundamental attributes of an OO language.
The only decent solution that has occurred to me is to invent an interface, ICClass, which only exposes the public methods, and have the Factory return ICClass interfaces.
This involves a fair amount of tedium - exposing all the naturally public properties again in the interface.
There are heaps of threads about this: Why does C# not provide the C++ style 'friend' keyword?
"Robot needs to use owner.mem here, but can't because it's private"
I think you want Protected with an inheritance model:
class C
{
protected Member mem;
protected Robot bot;
}
private class Robot : C
{
public void function() {
base.mem... // here you can use the base classes mem and bot
};
}
i am sorry if this has been asked before, but i don't really know if i'm phrasing the question right:
So, let's say i have this classes:
class Shape{
int Area
}
class Triangle:Shape{
string type_of_triangle;
}
class Star:Shape{
int Number_of_Points;
}
and a function that returns a shape typed List wich contains both triangle and shape objects in it. when i try to access triangle's or star's properties, visual studio only let's me access the parent's properties.
So, basically my question is: How can i access the child's properties if the objects are stored in a parent-type variable??
Shape unknownShape = new Triangle();
if(unknownShape is Triangle){
((Triangle)unknownShape).type_of_triangle;
}
I would suggest giving a little more thought to the design of you class hierarchy. Off the top of my head I would propose you can place all of the properties you have defined for your derived shapes within the parent. Further, you might want to consider making some of them methods which return values.
While it is not part of your current example, any shape, including a circle has a finite number of points (a circle simply has zero). A generic "shape_family" property might represent the string classification for the specific derivation of the shape class ("Triangle", "Star", etc).
The shape_subtype might represent specific variations ("Right Triangle", "Isoceles Triangle", etc.). Then, if you define the points as, well, POINTS and add them to a list, you will not only have specified locations for them (if that is not beyond the scope of your program), but you will have a count as well. From there you can probably work out some additional logic to map the sides/verticals, and compute such things as Area, perimeter, etc.
Consider (but please note that I am only now branching into C# and Java from vb.net, so if I butcher the code here, try to focus on the class structure, NOT my syntax . . .):
Edit: 4/22/2011 7:41 AM - Ooops. Forgot to make the Class abstract. If methods on a class are defined as "abstract", then the class itself must be abstract as well, meaning the abstract base cannot be directly instantiated. Here is a link to more info on abstract classes and methods/
public abstract class Shape
{
int Area;
string shape_family;
string shape_subtype;
list<point> Points
public int number_of_points()
{
return points.count
}
public abstract int perimeter_lenngth()
public abstract int area()
}
class Triangle : Shape {
//Example of Triangle-specific implementation:
public override int perimiter_length {
//You code to obtain and compute the lengths of the sides
}
//Example of Triangle-specific implementation:
public override int area {
//Your code to obtain and compute
}
}
class Star : Shape{
//Example of Star-specific implementation:
public override int perimiter_length {
//Your code to obtain and compute the lengths of the sides
}
//Example of Star-specific implementation:
public override int area {
//Your code to obtain and compute
}
}
class Circle : Shape {
point center;
int radius
// Example of Circle-specific implementation:
public override int perimiter_length {
return 2*3.14*radius
}
// Example of Circle-specific implementation:
public override int area {
return 3.14*radius^2
}
}
I see many methods that specify an interface as return value. Is my thought true that it means: my method can return every class type that inherits from that interface? if not please give me a good answer.
Yes, your method could return any type that implements that interface.
Here is an example:
using System;
class Foo
{
public IComparable GetComparable()
{
// Either of these return statements
// would be valid since both System.Int32
return 4;
// and System.String
return "4";
// implement System.IComparable
}
}
Yes, it means that the only thing you know about the object that is returned is that it implements the interface.
In fact, the actual type of the object may not even be accessible to the calling code. It could be a private type in a separate assembly.
And in fact, the method may return a different type from one invocation to the next (as in the case of an abstract factory).
Yes, that method might return an object of any type that implements that interface.
But, to use the non-interface members of a particular type, you'll need to cast it to that type.
C++ supports a programming technique called polymorphism. That is a derived class can look like a base class to other code that knows nothing about the derived classes. Take a look at his example:
class Shape
{
public:
virtual float Area () const = 0;
};
class Rectangle: public Shape
{
public:
Rectangle (float width, float height)
: m_width(width)
, m_height(height)
{}
virtual float Area () const
{
return m_width * m_height;
}
private:
float m_width;
float m_height;
};
class Circle: public Shape
{
public:
Circle (float radius)
: m_radius(radius)
{}
virtual float Area () const
{
return 3.141592653f*(m_radius*m_radius);
}
private:
float m_radius;
};
Now you can see from this code we've created a base class Shape (our interface) and two derived classes that specialise this class, one a rectangle, another a circle. Now let's create a function that prints out the area of a shape:
void PrintArea (const Shape& shape)
{
printf("Area of shape = %f",shape.Area());
}
This function doesn't care if its a circle of rectangle. Or it cares about is that it's passed a shape and that you can get the area of it, regardless of type.
So this code uses this function:
Rectangle r (5.0f,4.0f);
Circle c (25.0f);
PrintArea(r); // Print the area of the rectangle
PrintArea(c); // Print the area of the circle
Hope this helps.