inherited variable of class2 is different from class1 (C#) - c#

I just made a class Shapes and an other 2 classes ('Triangle' & 'Square') which inherit from 'Shapes'.
public class Shapes
{
private int sides;
}
public class Triangle : Shapes
{
public void init()
{
int sides = 3;
throw new System.NotImplementedException();
}
}
public class Square : Shapes
{
public void init()
{
int sides = 4;
throw new System.NotImplementedException();
}
}
Code is designed using Classdiagram
Question: How should I call the class so that it shows how many sides does a shape has?
Thanks

You need a protected member sides which is used within the init-section of every shape:
public class Shapes
{
protected readonly int sides;
public int NumberOfSides { get { return sides; } }
}
public class Triangle : Shapes
{
public Triangle()
{
this.sides = 3;
}
}
public class Square : Shapes
{
public Square()
{
this.sides = 4;
}
}
As Farhad Jabiyev mentioned using constructors is the usual way to initialize a new instance (see my code above)
Now when you call Shape#NumberOfSides you get 3 for Triangle and 4 for Square:
Shape square = new Square();
int number = square.NumberOfSides();

You need to add a property on the class that has an accessor like this
public class Shapes
{
private int sides;
public int NumberOfSides { get { return sides; } }
}
Then you can go mySquare.NumberOfSides

Related

Why do the properties in my code not work?

I have created an interface and then derived a class from it:
public interface Ishape
{
void draw();
int Number { get; set; }
}
class Circle : Ishape
{
public Circle(int a)
{
number = a;
}
public void draw()
{
Console.WriteLine("Circle.");
}
private int number;
public int Number
{
get
{
return number;
}
set
{
if (value < -5)
number = -5;
}
}
public int GetNumber()
{
return number;
}
}
class Program
{
static void Main(string[] args)
{
Circle a1 = new Circle(-6);
Console.WriteLine(a1.GetNumber());
Console.ReadLine();
}
}
As you can see, there is an autoproperty in the interface. I then decided to create a property in the new class that derived from the interface that would set the variable "number" to -5 if the value is less than -5. For some reason, the property does not seem to be working. Using the constructor, I set the value of the variable to -6, and the property did not change the value to -5. Why?
This is because you are setting number = a and not Number = a in your constructor. Try this:
public Circle(int a)
{
Number = a;
}
Your Number Property is never actually set.
In your Circle constructor, change number to Number.
public Circle(int a)
{
Number = a;
}
Also, if you intend to use GetNumber as your publicly available get (and nothing more), then I would advise that you change the access modifier for your Number property in your Circle class.

Encapsulating inner class and acessing outside in C#

I have these classes, one is a model, other is Listener and the third one is an Util class. I want to access Terrains by the variable map in the first one, but don't want public access to the inner class Terrain. Is there any way to do it?
It prints error CS0052: Inconsistent accessibility: field type
System.Collections.Generic.List is less
accessible than field `MapaMundiInfoScript.map'
public class MapaMundiInfoScript : MonoBehaviour {
public static bool changeInMap= false;
public static List<Terrain>map = new List<Terrain>();
void Start(){
Terrain terrain = new Terrain(0,0);
Terrain.TerrainPart initialPart = new Terrain.TerrainPart(20,20,0,0);
terrain.terrainParts.Add (initialPart);
map.Add(terrain);
changeInMap=true;
}
class Terrain{
int XPosition;
int ZPosition;
public List <TerrainPart> terrainParts = new List<TerrainPart> ();
public Terrain(int XPosition, int ZPosition){
this.XPosition=XPosition; this.ZPosition=ZPosition;
}
public class TerrainPart
{
int XSize;
int ZSize;
int XPosition;
int ZPosition;
TerrainPartReturn ReturnTerrainPart(int num1,int num2,int num3,int num4)
{
return new TerrainPart (num1,num2,num3,num4);
}
public TerrainPart(int XSize,int ZSize,int XPosition,int ZPosition){
this.XSize = XSize;
this.ZSize = ZSize;
this.XPosition=XPosition;
this.ZPosition =ZPosition;
}
}
}
public class MapListener : MonoBehaviour {
void Update () {
if (MapaMundiInfoScript.changeInMap) {
foreach(MapaMundiInfoScript.Terrain terrain in MapaMundiInfoScript.mapMundi)
{
foreach(terrain.terrainPart terrainPart in terrain.terrainParts)
{
RegionDraw.Draw(terrainPart);
}
}
MapaMundiInfoScript.changeInMap = false;
}
}
public class RegionDraw
{
/***
Implementantion Draw Method
***/
}
You cannot reference a private class as a public property. You will need to have the class public for public access. Consider making your properties and methods private, private protected, internal etc.
If you need to provide read only attributes, you can use public getters and private setters, etc. If you need to prevent the execution of some methods consider setting those to private, etc. The class can be public while still locking down properties and methods inside the class. Consider what it is that you actually need to expose.
You could also expose the functionality of these hidden classes through interfaces
public interface ITerrain
{
List<ITerrainPart> TerrainParts { get; }
ITerrainPart CreateTerrainPart(int XSize, int ZSize, int XPosition, int ZPosition);
}
public interface ITerrainPart
{
// ...
}
Implement them like this
private class Terrain : ITerrain
{
int XPosition;
int ZPosition;
public List<ITerrainPart> TerrainParts { get; } = new List<ITerrainPart>();
public Terrain(int XPosition, int ZPosition)
{
this.XPosition = XPosition; this.ZPosition = ZPosition;
}
public ITerrainPart CreateTerrainPart(int XSize, int ZSize, int XPosition,
int ZPosition)
{
return new TerrainPart(XSize, ZSize, ZPosition, ZPosition);
}
private class TerrainPart : ITerrainPart
{
// ...
}
}
Your listener can then draw like this (after changing the parameter type of Draw to ITerrainPart):
void Update()
{
if (MapaMundiInfoScript.changeInMap) {
foreach (ITerrain terrain in MapaMundiInfoScript.map) {
foreach (ITerrainPart terrainPart in terrain.TerrainParts) {
RegionDraw.Draw(terrainPart);
}
}
MapaMundiInfoScript.changeInMap = false;
}
}
Let MapaMundiInfoScript have a method DrawTerrain() and let Terrain have a method DrawParts. Should you end up with to many incoherent methods in MapaMundiInfoScript, you might want to use a visitor.

Only allow certain classes to edit certain properties

I have a class with a PictureBox created as followed:
public class Tile
{
public PictureBox tilePB = new PictureBox(); //properties don't matter in this case
}
I also have a class GameManager. This is like a referee.
I want to make it so the BackColor of Tile.tilePB can only be edited by Gamemanager and nothing else, and no other class.
I currently have a public PictureBox for Gamemanager (to edit) and a public get function for other classes, but I want to actually make this a valid system instead of what I have right now.
Is this even possible? Please include explenation for the required code.
EDIT: I ran into an issue that I hadn't thought off: class Gamemanager is a static class. I do everything in that class via public static functions. Is this still possible? Since this doesn't work.
You can't do this at compile time, but it can be done at runtime:
public class PictureBox
{
private Color _backColor;
public void SetBackColor(Color color)
{
//getting class type that called this method
var stackTrace = new StackTrace();
var stackFrames = stackTrace.GetFrames();
var callingFrame = stackFrames[1];
var method = callingFrame.GetMethod();
//checking if the class type is GameManager
if (!method.DeclaringType.IsAssignableFrom(typeof(GameManager)))
{
throw new FieldAccessException("Only GameManager can set the background color of a PictureBox!");
}
_backColor = color;
}
public Color BackColor => _backColor;
}
public class Tile
{
public PictureBox tilePB { get; set; }
}
//example GameManager class
public class GameManager
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
//example class that may want to set picturebox background color
public class MaliciousClass
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
Then somewhere:
var gm = new GameManager();
var mc = new MaliciousClass();
gm.SetBackground(); //this is fine
mc.SetBackground(); //this will throw an exception
If you don't want to throw an exception or you want to do something different when "not authorized" class is trying to access the SetBackColor method then just replace throw new FieldAccessException() with return or whatever you want.
Bare in mind the approach presented here is inefficent and it just presents that in can be done at runtime and nothing more than that.
Not sure if this is exactly what you are looking for, but I made this quick test and it seems to be able to differentiate the calling class:
class Program
{
static void Main(string[] args)
{
Type1 something1 = new Type1();
Type2 something2 = new Type2();
something1.runTest();
something2.runTest();
Console.ReadKey();
}
public class Type1
{
public void runTest()
{
Testing.edit(this);
}
}
public class Type2
{
public void runTest()
{
Testing.edit(this);
}
}
public static class Testing
{
public static void edit(object obj)
{
// This is where you test the calling class to make sure
// it is allowed to edit.
Console.WriteLine(obj.GetType().ToString());
}
}
}
The only way I can think of where you enforce this at compile time, end up being a bit complicated. I don't think you'll want to do this.
You can create an interface with properties/methods for everything that only the GameManager is allowed to do. You can implement this interface in a private inner class below Tile, and make sure the only way this object is created is by passing in a GameManager that receives it. Now, the only way the access can 'leak' is if the GameManager 'gives away' the object.
public class GameManager {
public void AddTile(Tile t, Tile.IManagerHook m) {
m.SomeProperty = "set from manager";
}
}
public class Tile
{
public object SomeProperty { get; private set; }
public Tile(GameManager manager) {
manager.AddTile(this, new ManagerHook(this));
}
public interface IManagerHook {
object SomeProperty {get; set;}
}
private class ManagerHook : IManagerHook {
private Tile _tile;
public ManagerHook(Tile t) {
_tile = t;
}
public object SomeProperty {
get{ return _tile.SomeProperty;}
set { _tile.SomeProperty = value; }
}
}
}
(seems) Simply not possible
After asking several programmers, the way I have coded everything and what I want seems to be simply impossible without immensely complicated code - to the point you are better off refacturing everything. Since class Gamemanager is a static class, there will be no instances of it so you can not check if the 'object' that called it is of class Gamemanager. this also doesn't work since Gamemanager is, agian, static.

inheritence C# using new functions

I'm making a game in C#. I created a base class Shape and seven other classes (Shape1, Shape2, ...) that inherit from Shape. In my main program I keep track of the shape currently in play by using
Shape Current;
Then I randomise its value to be equal to one of the shapes, for example:
Current = new Shape1()
The problem is, after I randomise I want to draw the shape with
Current.Draw()
Each shape has its own Draw function, and I want it to use that function specificly, and not the function in Shape. How can I do that?
The concept you are describing is called polymorphism (treating different object types as one).
In C#, you do this via the virtual, abstract and override keywords. In the base class, you mark the polymorphic method as either virtual or abstract, with the difference being abstract methods must be defined by derived classes:
public abstract void Draw();
Note that virtual methods must define a body, while abstract methods must not. Then in the derived class you define the same method with the override keyword:
public override void Draw()
{
//whatever implementation
}
For far more information, see MSDN
I must say #BradleyDotNet explained it very well, I'm just adding a practical example that may help to clarify the use of it.
Notice how I used all virtual, abstract and override keywords.
using System;
namespace ShapeExample
{
class Program
{
public static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
var shape = GetRandomShape();
shape.Draw();
}
}
public static Random Random = new Random();
public static Shape GetRandomShape()
{
var d = Random.Next(3);
switch (d)
{
case 1:
return new Shape1();
case 2:
return new Shape2();
default:
return new Shape3();
}
}
}
public abstract class Shape
{
public virtual void Draw()
{
//Console.WriteLine("General Shape");
Console.WriteLine(" _");
Console.WriteLine(" / \\ ");
Console.WriteLine("/___\\");
}
}
public class Shape1 : Shape
{
public override void Draw()
{
//Console.WriteLine("I want a square instead");
Console.WriteLine(" ____");
Console.WriteLine("| |");
Console.WriteLine("|____|");
}
}
public class Shape2 : Shape
{
public override void Draw()
{
//Console.WriteLine("I want a complicated circle instead");
double r = 3.0;
double r_in = r - 0.4;
double r_out = r + 0.4;
for (double y = r; y >= -r; --y)
{
for (double x = -r; x < r_out; x += 0.5)
{
double value = x * x + y * y;
if (value >= r_in * r_in && value <= r_out * r_out)
{
Console.Write('*');
}
else
{
Console.Write(' ');
}
}
Console.WriteLine();
}
}
}
public class Shape3 : Shape
{
//I don't care how I look like, I'm using the regular shape drawing.
//but I have some particular info that is not part of a regular Shape
public int ParticularField { get; }
public Shape3()
{
ParticularField = -100;
}
}
}

How can I access members of a private abstract to class for read-only purposes in a public class?

I have a private abstract class called TDSeq in which there are some abstract members and non-abstract members. There are 2 derived classes which it gets data from:- private class TDSeqBuy: TDSeq and private class TDSeqSell: TDSeq.
The members from the private abstract class that I am trying to access are private/public bools/doubles/integers.
The data flows from the derived classes through to the private abstract class by protected abstract name {get;}. After which the data is "moved" to the above mentioned private/public bool/doubles/integers.
I would like to access data for read-only purposes from the abstract class to a public class but do not know how to do that. Could someone please help?
private abstract class TDSeq
{
public event SetupCompletedEventHandler SetupCompleted;
protected abstract double TDSTHigh { get; }
protected abstract double TDSTLow { get; }
protected abstract double SetupStopLevel { get; }
public double highesthigh = 0;
public double lowestlow = 0;
public double truerange = 0;
public double setupstoplevel = 0;
// ...
case TDSTStateSetup.Completed:
if( ValidSetup )
{
Print = "ValidExtSetup";
setupCount++;
SetupDrawText();
//Print = NameIndex;
}
else
{
Print = "ExtSetup Finalised";
tdsetupiscompleted = true;
if (tdsetupiscompleted)
{
Print = "tdsetupiscompleted";
}
if (tdsetupdirection == 1)
{
Print = "tdsellsetupiscompleted";
}
if (tdsetupdirection == -1)
{
Print = "tdbuysetupiscompleted";
}
highesthigh = TDSTHigh;
lowestlow = TDSTLow;
truerange = (highesthigh - lowestlow);
setupstoplevel = SetupStopLevel;
stateSetup = TDSTStateSetup.Finished;
}
// ...
}
I'm trying to publicly access the last 5 lines...
You can also use auto properties to acheive the same without using a private field.
e.g.
private abstract class A
{
protected int Number { get; private set; }
}
private class B : A
{
public int GetNumber()
{
return Number;
}
}
Use protected, not private. Also consider composition over inheritance.
Nested classes are not a good idea. It only limits scope. And protected will not save you there.
If you want access to the properties and them only to be read only, store the values in private fields - and give a protected get property to give read only access to the private fields like so:
private abstract class A
{
private int _number = 5;
protected int Number { get { return _number; } }
}
private class B : A
{
public int GetNumber()
{
return Number;
}
}
private class C : A
{
public int GetNumber()
{
return Number;
}
}
If you want to access data via an object of an abstract class A within a method of a separate, public class X, the abstract class has to be visible to X, so it has to be public (or at least internal, when A and X are part of the same assembly):
public class Program
{
static void Main(string[] args)
{
B b = new B();
X.Test(b);
}
// private does not work here if you want to have a parameter of type A in X
public abstract class A
{
private int _number = 5;
public int Number { get { return _number; } }
}
private class B : A
{
}
}
public class X
{
public static void Test(Program.A a)
{
Console.WriteLine(a.Number);
}
}
Top level classes in an assembly can only be public or internal in terms of accessibility, so I'm assuming your private abstract class and it's derived classes are all nested inside some public class, for starters. Correct?
If so, simply access members of the nested private abstract class that are non-abstract and public by first instantiating the private derived classes inside that parent class via say a public property, then simply call the public field from it:
public class TopClass
{
DerivedClass MyDerivedClass;
public int GetDerivedClassPublicField
{
get
{
DerivedClass MyDerivedClass = new DerivedClass();
return DerivedClass.myfield;//here is access to your abstract class field from outside
}
}
// Private classes must be nested
private abstract class AbstractClass
{
public int myfield = 1;
}
private class DerivedClass : AbstractClass
{
... (derived classes inherit the non-abstract field from the abstract parent by default here) ...
}
}
// now call the public top level class property to get the field in the abstract class
TopClass MyTopClass = new TopClass();
int myInt = MyTopClass.GetDerivedClassPublicField;

Categories