Problem with generic class variables acess - c#

Hello and sorry if I put the question or title incorrectly, I can’t formulate it in any way
I have a custom generic tiletype class with all information about the tile and in another script there is a bool CheckCondition();
I need to access the tileBase variable in the tileData class to use this in TileMap.GetTile<>() function
I have custom TileTypes class :
using System;
using UnityEngine;
using UnityEngine.Tilemaps;
public class TileTypes
{
[Serializable]
public class GroundTiles : TileData<GroundTileType>
{ }
[Serializable]
public class ObjectTiles : TileData<ObjectTileType>
{ }
public class TileData<T> : TileData
where T : Enum
{
public T TileType;
public override int TileTypeId { get { return Convert.ToInt32(TileType); } }
}
public abstract class TileData
{
public Sprite Sprite;
public Color Color;
public TileBase tileBase;
public Tile.ColliderType ColliderType;
public virtual int TileTypeId { get; }
public Item item;
}
}
have bool CheckCondition :
private bool CheckCondition(TileTypes.TileData tile, Item currentItem)
{
if(currentItem.type == ItemType.BuildingBlock)
{
if(!tile.tileBase)
{
return false;
}
}
else if(currentItem.type == ItemType.Tool)
{
if(tile.tileBase)
{
if(tile.item.actionType == currentItem.actionType)
{
return true;
}
}
}
return false;
}
and tryna do something like :
if(CheckCondition(TileMap.GetTile<TileTypes.TileData.tileBase>(pos), currentItem))

Related

can't get string value from inheritance

Can't get string value even tho in my Parent class it works properly and now that I'm getting it . It won't get its value
this my parent class
public class GameManagerRevamped : MonoBehaviour
{
public string finalAnswer;
public string TryInheritance;
public virtual void firstButtonClicked()
{
Debug.Log(TryInheritance);
}
public virtual void GetValuebtn()
{
TryInheritance = finalAnswer;
Debug.Log("this is working" +TryInheritance +finalAnswer);
}
}
Child Class
public class FableScript : GameManagerRevamped
{
public override void firstButtonClicked()
{
finalAnswer += "a";
base.firstButtonClicked();
}
}
GetValuebtn() method is never called therefore TryInheritance is always "".
I think you want to do the following:
public virtual void firstButtonClicked()
{
GetValuebtn();
Debug.Log(TryInheritance);
}

Inheritance with packages/namespaces [C#]

I want to redefine the classes of a package in a sub-package while keeping the hierarchy.
I would have wanted to do something like this :
namespace RPG {
public class Actor {}
public class Character : Actor {}
}
public class Actor : RPG.Actor {}
//kind of a diamond problem
public class Character : Actor, RPG.Character {}
I know this is incorrect ; C# doesn't support multiple inheritance, but I don't know the best way to resolve this kind of redefinition.
Interfaces doesn't solve my problem. I could do something like that using composition :
public class Character : Actor {
private RPG.Character basis;
// and do this for each attribute and method
public int atk { get { return basis.atk } set { basis.atk = value; } }
}
but it doesn't look good. Moreover, I ran into another problem with this way
namespace RPG {
public class Actor {
public List<Stat> stats { get; set; }
}
public class Stat {}
}
public class Actor {
private RPG.Actor basis;
//I can't do that because Stat does not inherit from RPG.Stat
public override List<RPG.Stat> stats { get; set; }
}
public class Stat {
private RPG.Stat basis;
}
What is the best way to resolve my problem ?
Use composition instead of inheritance.
It's tough to draw a direct example because you didn't provide any actions for your RPG actor/characters but the concept is that you inject the behaviors in the constructor of your class.
In this case "move" is the behavior:
class Fighter
{
public int Health = 100;
public string Name;
private Move _move;
public string MoveName
{
get
{
return _move.Name;
}
}
public int MoveDamage
{
get
{
return _move.Damage;
}
}
public Fighter(string name, Move defaultMove)
{
Name = name;
_move = defaultMove;
}
public void Attack(Fighter defendant)
{
if (_move != null)
_move.Attack(defendant);
}
public void SetMove(Move move)
{
if (move != null)
_move = move;
}
}
abstract class Move
{
public int Damage { get; set; }
public string Name { get; set; }
protected Move(int damage,string name)
{
Damage = damage;
Name = name;
}
public void Attack(Fighter defendant)
{
defendant.Health -= Damage;
}
}
class PunchMove:Move
{
public PunchMove() : base(5, "Punch")
{
}
}
class KickMove:Move
{
public KickMove() : base(7, "Kick")
{
}
}
try this.
namespace RPG {
public class Actor {
public void d(){
System.Console.Write("fhdf");
}
}
public class Character : Actor {}
}
////////////////
public class Character : RPG.Character {}
class Program
{
static void Main()
{
Character c = new Character();
c.d();
Console.WriteLine("Hello, World!");
}
}

List entries conform to both class and interface?

I have a the following C# classes and interfaces:
class NativeTool
class NativeWidget: NativeTool
class NativeGadget: NativeTool
// above classes defined by the API I am using. Below classes and interfaces defined by me.
interface ITool
interface IWidget: ITool
interface IGadget: ITool
class MyTool: NativeTool, ITool
class MyWidget: NativeWidget, IWidget
class MyGadget: NativeGadget, IGadget
Now, I would like MyTool to keep a list of children. The children will all conform to ITool and inherit from NativeTool. The classes MyTool, MyWidget, and MyGadget all fit these criteria.
My question is, is there any way to tell MyTool that its children will always inherit from both NativeTool and ITool? I can do one or the other easily enough. But both?
You may do something like:
public class MyTool<T,U> where T: ITool where U: NativeTool
{
}
and create this like:
var tool = new MyTool<MyWidget, MyWidget>();
and also derivates, like
public class MyWidget : MyTool<....>
{
}
This appears to do it. An annoying number of wrappers, but it gets the job done, without duplicating storage.
public interface ITool { }
public interface IWidget : ITool { }
public class NativeTool { }
public class NativeWidget : NativeTool { }
public class MyTool : NativeTool, ITool, INativeTool {
public MyTool() {
this.Children = new List<INativeTool>();
}
public ITool InterfacePayload { get { return this; } }
public NativeTool NativePayload { get { return this; } }
public List<INativeTool> Children { get; set; }
public NativeTool NativeChild(int index) {
return this.Children[index].NativePayload;
}
public ITool InterfaceChild(int index) {
return this.Children[index].InterfacePayload;
}
public void AddChild(MyTool child) {
this.Children.Add(child);
}
public void AddChild(MyWidget child) {
this.Children.Add(child);
}
}
public class MyWidget : NativeWidget, IWidget, INativeTool {
public ITool InterfacePayload { get { return this; } }
public NativeTool NativePayload { get { return this; } }
}
public interface INativeTool {
// the two payloads are expected to be the same object. However, the interface cannot enforce this.
NativeTool NativePayload { get; }
ITool InterfacePayload { get; }
}
public class ToolChild<TPayload>: INativeTool where TPayload : NativeTool, ITool, INativeTool {
public TPayload Payload { get; set; }
public NativeTool NativePayload {
get {return this.Payload;}
}
public ITool InterfacePayload {
get { return this.Payload; }
}
}

How to set a property in class from a derived class

I am not sure how this functions in C#.
I have a class:
public class FindIt()
{
}
public class FindItFrm()
{
private bool _amISet = false;
public FindItFrm()
{
}
public bool AmISet()
{
get { return _amISet; }
set { _amISet = value; }
}
}
And the class that I am working in has:
public class MyHelper() : FindIt
{
// Constructor
public MyHelper()
: base(new FindItFrm())
}
I want to set a property (AmISet) in the FindItFrm while inside the MyHelper class. How would I accomplish this?
Your code should look like this (in the future, please post working code for examples):
public class FindIt
{
// You need to let your derived class access the FindItFrm
protected FindItFrm Frm;
// Constructor needs to accept a FindItFrm
public FindIt(FindItFrm frm)
{
Frm = frm;
}
}
public class FindItFrm
{
private bool _amISet = false;
public bool AmISet
{
get { return _amISet; }
set { _amISet = value; }
}
}
public class MyHelper : FindIt
{
// Constructor
public MyHelper()
: base(new FindItFrm())
{
Frm.AmISet = true;
}
}

Relationship between two interfaces and two classes.

So I want to design a team/player relationship like this: every player belongs to one team but since I wanted to practice with interfaces I made ITeam and IAthlete and then made BasketballTeam and BasketballPlayer.
Then I wrote this code:
public interface IAthlete
{
string GetName();
string GetSport();
}
public interface ITeam
{
void AddPlayer(IAthlete player);
IAthlete[] GetAthletes();
string GetName();
int GetNumberOfPlayers();
}
public class BasketballPlayer:IAthlete
{
private string name;
public string GetName()
{
return this.name;
}
public string GetSport()
{
return "Basketball";
}
public BasketballPlayer(string name)
{
this.name = name;
}
public void Run(int distance)
{
Console.WriteLine(this.name + " just ran " + distance.ToString() + " meters.");
}
public bool Shoot()
{
Console.WriteLine("Successful shot for " + this.name);
return true;
}
}
public class BasketballTeam: ITeam
{
BasketballPlayer[] players;
int numberOfPlayers;
private string name;
public void AddPlayer(BasketballPlayer player)
{
this.players[this.numberOfPlayers] = player;
this.numberOfPlayers++;
}
public IAthlete[] GetAthletes()
{
return this.players;
}
public string GetName()
{
return this.name;
}
public int GetNumberOfPlayers()
{
return this.numberOfPlayers;
}
public BasketballTeam(string name)
{
this.numberOfPlayers = 0;
this.name = name;
this.players = new BasketballPlayer[10];
}
}
class Program
{
static void Main(string[] args)
{
BasketballTeam bt = new BasketballTeam("MyTeam");
BasketballPlayer bp = new BasketballPlayer("Bob");
bt.AddPlayer(bp);
foreach (BasketballPlayer player in bt.GetAthletes())
{
Console.WriteLine(player.GetName());
}
foreach (IAthlete a in bt.GetAthletes())
{
Console.WriteLine(a.GetName());
}
}
}
But it won't compile because I'm using this:
public void AddPlayer(BasketballPlayer player)
in the BasketballPlayer instead of this
public void AddPlayer(IAthlete player)
I thought it should work because BasketballPlayer is an IAthlete.
And if I change it to IAthlete then I can make another class like this:
public class HockeyPlayer : IAthlete
{
private string name;
public string GetName()
{
return this.name;
}
public string GetSport()
{
return "Hockey";
}
public HockeyPlayer(string name)
{
this.name = name;
}
public void Run(int distance)
{
Console.WriteLine(this.name + " just ran " + distance.ToString() + " meters.");
}
}
and then do this in my main:
HockeyPlayer hp = new HockeyPlayer("Henry");
bt.AddPlayer(hp);
which is logically wrong because I'm adding HockeyPlayer to a BasketballTeam. Is it supposed to be like this and I should just be careful not to do that? What am I doing wrong? How do I show this using class diagrams? Does this lead to loose coupling?
You're trying to violate the Liskov Substitution Principle.
Anything that can be done with a supertype – such as adding a HockeyPlayer – can also be done with a subtype – including a BasketballTeam.
Instead, you should use generics:
class Team<TPlayer> where TPlayer : IAthlete {
public ReadOnlyCollection<TPlayer> Players { get; }
public string Name { get; }
public void AddPlayer(TPlayer player);
}
Here is some thoughts on your code. First, in C# you can use properties, instead of Get and Set methods.
public interface IAthlete
{
string Name { get; }
string Sport { get; }
}
With auto-properties you can ask compiler to generate back store for property. Also consider creating base class Player, which will hold implementation of Name and Sport properties.
public class Player : IAthlete
{
public Player(string name, string sport)
{
Name = name;
Sport = sport;
}
public string Name { get; private set; }
public string Sport { get; private set; }
}
Now when implementing some player, you can just pass values to base class constructor. And your custom players will hold only specific for them functionality (no code duplication). Also it's recommended to use string format, instead of concatenating strings:
public class BasketballPlayer : Player
{
public BasketballPlayer(string name)
: base(name, "Basketball")
{
}
public void Run(int distance)
{
Console.WriteLine("{0} just ran {1} meters.", Name, distance);
}
public bool Shoot()
{
Console.WriteLine("Successful shot for " + Name);
return true;
}
}
Now about teams. If you don't want to have FootballPlayers in your BasketballTeam, then you should create parametrized team. Also consider using IEnumerable:
public interface ITeam<TPlayer>
where TPlayer : IAthlete
{
void AddPlayer(TPlayer player);
IEnumerable<TPlayer> Players { get; }
string Name { get; }
int NumberOfPlayers { get; }
}
Again, for common functionality you can create base class. Keep in mind, that you should check how many players currently in your team before adding new player.
public class Team<TPlayer> : ITeam<TPlayer>
where TPlayer : IAthlete
{
private readonly List<TPlayer> _players = new List<TPlayer>();
public Team(string name, int teamSize)
{
Name = name;
TeamSize = teamSize;
}
public void AddPlayer(TPlayer player)
{
if (_players.Count == TeamSize)
throw new Exception("Players number exceeded");
_players.Add(player);
}
public string Name { get; private set; }
public int TeamSize { get; private set; }
public IEnumerable<TPlayer> Players
{
get { return _players; }
}
public int NumberOfPlayers
{
get { return _players.Count; }
}
}
And custom team implementation becomes really easy. You just tell which type of players it will have, and pass to base team implementation team name and size of team.
public class BasketballTeam : Team<BasketballPlayer>
{
public BasketballTeam(string name)
: base(name, 10)
{
}
}
Now your program works like a charm:
class Program
{
static void Main(string[] args)
{
BasketballTeam bt = new BasketballTeam("MyTeam");
BasketballPlayer bp = new BasketballPlayer("Bob");
bt.AddPlayer(bp);
foreach (BasketballPlayer player in bt.Players)
{
Console.WriteLine(player.Name);
}
foreach (IAthlete a in bt.Players)
{
Console.WriteLine(a.Name);
}
}
}
Logically ,
These should be your base classes : Team , Player
These should be your derived classes : BasketballTeam , BasketballPalyer
These should be interfaces on Player : IPlay() , IRun , IGetName etc.. whichever applicable
and so on...
Guideline : Verbs suits more good on interfaces and Noun suits good on classes. Noun in the requirement best suits for Class in the code.
SLaks is correct. You could add a generic constraint to your ITeam to not accept all players, but just those of one type:
public interface ITeam<T> where T : IAthlete
{
void AddPlayer(T player);
IAthlete[] GetAthletes();
// or: T[] GetAthletes();
string GetName();
int GetNumberOfPlayers();
}
A BasketballTeam implementation could look like:
public class BasketballTeam : ITeam<BasketballPlayer>
{
BasketballPlayer[] players;
// […]
public void AddPlayer(BasketballPlayer player)
{
this.players[this.numberOfPlayers] = player;
this.numberOfPlayers++;
}
public IAthlete[] GetAthletes()
{
return this.players;
}
// or:
// public BasketballPlayer[] GetAthletes()
// {
// return this.players;
// }
// […]
}
If your interfaces are meant to be used by variety of games, it seems that you are missing the Game here and perhaps need to use Generics:
public interface IGame
{
string Name {get;}
...
}
public class Bastketball : IGame
{
...
}
public interface ITeam<TGame> where TGame: class, IGame
{
void AddPlayer(IPlayr<TGame> player);
...
}
public interface IPlayer<TGame> where TGame: class, IGame
{
...
}
This will prevent from hockey player to be added to Basketball team.

Categories