Hi everyone I am programming in Unity3d with C# and while I was writing my code I stumbled with a little issue, I write to you an example because I dont know explain me.
class Base
{
public string name;
}
class Derived : Base
{
public void Gun();
}
class BasePlayer
{
public Base x;
}
class SoldierPlayer : BasePlayer
{
}
The situation is this, I want to do something like that
SoldierPlayer.x.Gun();
But I don't know how do it
The real case is this
public class BasePlayerController : MonoBehaviour
{
public BasePlayerManager playerManager;
...
public class RobotPlayerController : BasePlayerController {
...
playerManager = gameObject.AddComponent<RobotPlayerManager>();
And I will use new methods
UPDATE 1
I did a example better, I want to do in Base Controller manager.user.energy and be treated as the next type RobotManager.RobotUser.energy
BaseController
BaseManager
BaseUser
class BaseController
{
BaseManager manager;
public virtual void Move(int x,int y)...
}
class BaseManager {
BaseUser user;
public virtual Pause(bool state);
}
class BaseUser {
int life
}
RobotController
RobotManager
RobotUser
class RobotController : BaseController
{
// manager as RobotManager?
public void Ray(int x,int y);
}
class RobotManager : BaseManager
{
// user as RobotUser?
}
class RobotUser : BaseUser
{
int energy;
}
UPDATE 2
I seek to do this
public Run()
{
RobotController rc = new RobotController();
rc.manager.energy;
}
You can't call SoldierPlayer.x.Gun(); because SoldierPlayer.x has type Base which has not method Gun(). OOP world and C# can provide you many solutions, your choose depends on your goals.
some of them (order by best practise):
1) Overriding Polymorphism. Add .Gun() method to Base class and implemend it in derived classes. For example
class Base
{
public string name;
public void virtual Gun()
{
Trace.Log("I'm base class, i can't do anything");
}
}
class Derived : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have gun");
}
}
class Derived2 : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have 2 guns");
}
}
2) Overloading Polymorphism In many source this method is mentioned like some kind of polymorphism AD-HOC
public void GunAction(Derived2 o)
{
o.Gun();
}
public void GunAction(Derived1 o)
{
o.Gun();
}
public void GunAction(Base o)
{
Trace.Log("I'm base class, i can't do anything");
}
3) is-cast
public void GunAction(Base o)
{
if(o is Derived1 )
o.Gun();
if(o is Derived2 )
o.Gun();
}
UPDATE 1 answering to your new requirements
class BaseController
{
public BaseManager manager;
...
class RobotController1 : BaseController
{
// manager as RobotManager? - no it is stil BaseManager
public void Ray(int x,int y);
}
class RobotController2 : BaseController
{
// manager as RobotManager? - yes. now it is RobotManager
public void Ray(int x,int y);
public RobotController2()
{
manager = new RobotManager();
}
}
public void Run()
{
var controller = new RobotController2();// you have RobotManager
controller.manager = new BaseManager();// it is again BaseManager
}
Related
I want to reuse Cook method functionality, but still pass different parameters to execute:
public void Cook(BasicRequest request,IBaseInterface base)
{
// Some code
// More code
request.Execute(base);
}
public class BasicRequest
{
public abstract void Execute(IBaseInterface baseInterface)
}
public class RequestA : BasicRequest
{
public void Execute(IBaseInterface base)
{
var derived = (DerivedClassA)base;
// Do stuff with derived
}
}
public class RequestB : BasicRequest
{
public void Execute(IBaseInterface base)
{
var derived = (DerivedClassB)base;
// Do stuff with derived
}
}
public interface IDerivedClassA : IBaseInterface {}
public interface IDerivedClassB : IBaseInterface {}
I have a design issue here that casting is needed on each of requests execute methods.
How can I make this code cleaner ?
You should be using generics.
Update the BaseRequest to a generic class:
public abstract class BasicRequest<T> where T:IBaseInterface
{
public abstract void Execute(T baseInterface);
}
Change your class Cook method as follows:
public void Cook<T>(BasicRequest<T> request, T ibase) where T:IBaseInterface
{
// Some code
// More code
request.Execute(ibase);
}
Change your classes,
public class RequestA : BasicRequest<DerivedClassA>
{
public override void Execute(DerivedClassA ibase)
{
// Do stuff with derived
}
}
public class RequestB : BasicRequest<DerivedClassB>
{
public override void Execute(DerivedClassB ibase)
{
// Do stuff with derived
}
}
I'm trying to implement a generic abstract method with a type constraint, then Implement it multiple times using different specified types.
public abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
public class DashAbility : Ability
{
public override void BindToStation<NavStation>(NavStation station){ }
public override void BindToStation<CannonStation>(CannonStation station){ }
}
But I get an error which says the method has already been defined with the same paramater types.
I'm guessing that the compiler treats any generic paramater as the same in terms of the method signature, so these two methods look the same to it.
Still though, I'm wondering if theres a way to have generic method overloading using specific types.. ?
You can't do exactly what you want, but you can try an approach like this:
interface IBindableTo<T> where T : Station
{
void BindToStation(T station);
}
abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
class DashAbility : Ability, IBindableTo<NavStation>, IBindableTo<CannonStation>
{
public override void BindToStation<T>(T station)
{
if (this is IBindableTo<T> binnder)
{
binnder.BindToStation(station);
return;
}
throw new NotSupportedException();
}
void IBindableTo<NavStation>.BindToStation(NavStation station)
{
...
}
void IBindableTo<CannonStation>.BindToStation(CannonStation station)
{
...
}
}
Hope this helps.
C# doesn't support specialization in that way, and neither does C++ easily when you want to specialize on runtime type.
But you can use polymorphism, so you can use double-dispatch:
public abstract class Station {
internal abstract void DashBindToStation();
}
public class NavStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public class CannonStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public override void BindToStation(Station station) {
station.DashBindToStation();
}
}
Another possibility with C# is to use runtime dispatching using dynamic:
public abstract class Station {
}
public class NavStation : Station {
}
public class CannonStation : Station {
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public void BindToStation(NavStation station) {
}
public void BindToStation(CannonStation station) {
}
public override void BindToStation(Station station) {
BindToStation((dynamic)station);
}
}
I have to do a simple rpg game and there are 2 types of entities: heroes and monsters. Attack method will be implemented in both classes and it is contained by a interface called IAttack. The problem is that this method take a Monster type as parameter for hero class and a Hero type as parameter for monster class.
The code looks something like this:
The interface:
interface IAttack
{
void Attack(Object oponnnent);
}
The Hero class(which implements IAttack):
public void Attack(Monster opponent)
{
//code goes here
}
The Monster class(which implements IAttack):
public void Attack(Hero opponent)
{
//code goes here
}
The problem is I can not pass different types of arguments.
You could make an abstract class that Monster and Hero dervice from.
public abstract class PlayerType
{
public abstract int Health();
}
Then in your interface use the new abstract type:
interface IAttack
{
void Attack(PlayerType oponnnent);
}
Monster class:
public class Monster : PlayerType, IAttack
{
public override int Health()
{
return 100;
}
public void Attack(PlayerType hero)
{
}
}
Hero class:
public class Hero : PlayerType, IAttack
{
public override int Health()
{
return 500; // He is a hero afterall ;)
}
public void Attack(PlayerType monster)
{
}
}
Why not have two interfaces? Something that can attack and something that can be attacked?
public interface IAttackable
{
void OnAttacked(IAttacker attacker);
}
public interface IAttacker
{
void OnAttack(IAttackable opponet);
}
public class Hero : IAttacker, IAttackable
{
public void OnAttack(IAttackable opponet)
{
}
public void OnAttacked(IAttacker attacker)
{
}
}
public class Monster : IAttacker, IAttackable
{
public void OnAttack(IAttackable opponet)
{
}
public void OnAttacked(IAttacker attacker)
{
}
}
The code is simple enough to understand I hope.
I'm trying to use an interface type IColor in order to pass color objects to the ColorManager. I then want the ColorManager to pass this object to the IColor object as its own type, so the method overloads gets called.
However, it seems since it is being passed as the IColor type, C# will not implicity cast it into its complete type as either a BlueColor or GreenColor.
I hope this makes some sense to somebody on what I want to achieve. Is this possible in C#?
[Solution]
http://msdn.microsoft.com/en-us/library/dd264736.aspx
Overload Resolution with Arguments of Type dynamic
My code so far:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
namespace Example
{
public interface IColor
{
void CatchColor(IColor c);
}
public class BlueColor : IColor
{
public void CatchColor(IColor c)
{
}
}
public class GreenColor : IColor
{
public void CatchColor(BlueColor c)
{
Console.WriteLine("CAUGHT BLUE!");
}
public void CatchColor(GreenColor c)
{
Console.WriteLine("CAUGHT GREEN!");
}
public void CatchColor(IColor c)
{
Console.WriteLine("CAUGHT SOME COLOR!");
}
}
public class ColorManager
{
public void PassColor(IColor c)
{
// Don't use static type-checking
// Problem solved
dynamic AnyColor = c;
AnyColor.CatchColor(AnyColor);
}
public static void Main()
{
GreenColor G = new GreenColor();
new ColorManager().PassColor(G);
Console.ReadLine();
return;
}
}
}
One possiblity to tell the ColorManager class to use the correct type of the passed object is to use an abstract class, that already implements the CatchColor:
public abstract class IColor
{
// override in every class
public abstract void PrintColor();
// has the correct type passed with the interface
public void CatchColor(IColor c)
{
c.PrintColor();
}
}
Then the sub classes need to implement only PrintColor with the correct color:
public class BlueColor : IColor
{
public override void PrintColor()
{
Console.WriteLine("BLUE!");
}
}
public class GreenColor : IColor
{
public override void PrintColor()
{
Console.WriteLine("GREEN!");
}
}
The manager is the same:
public class ColorManager
{
public void PassColor(IColor c)
{
c.CatchColor(c);
}
}
It can be used like this:
GreenColor G = new GreenColor();
var cm = new ColorManager();
cm.PassColor(G);
cm.PassColor(new BlueColor());
The outputs is:
GREEN!
BLUE!
What you want is late method binding.
The downside to this is you have to add methods for each new type of color. The upside is you don't have to maintain a case statement or conditional logic.
See here for more detail:
Early and late binding
Edit: Here is a working example of this type of late-binding.
class Program {
static void Main(string[] args) {
//Declare instances
BaseClass myClass = new Class2();
BaseClass otherClass = new Class1();
//Invoke the action method which will match based on the BaseClass type
Action(myClass);
Action(otherClass);
Console.ReadLine();
}
public static void Action(BaseClass classType) {
//Remove the compile-time type so the runtime can select the method based on signature
dynamic aClass = classType;
ServiceMethod(aClass);
}
public static void ServiceMethod(dynamic input) {
Methods(input);
}
public static void Methods(Class1 classType) {
Console.WriteLine("Class1");
Debug.WriteLine("Class1");
}
public static void Methods(Class2 classtype) {
Console.WriteLine("Class2");
Debug.WriteLine("Class2");
}
public static void Methods(Class3 classType) {
Console.WriteLine("Class3");
Debug.WriteLine("Class3");
}
}
public abstract class BaseClass { //This could also be an interface
public Guid Id { get; set; }
public string Name { get; set; }
}
public class Class1 : BaseClass {
}
public class Class2 : BaseClass{
}
public class Class3 : BaseClass {
}
So you want something like:
public void CatchColor(Color c)
{
if (c is BlueColor)
CatchColor(c as BlueColor);
if (c is GreenColor)
CatchColor(c as GreenColor);
}
?
is this possible to somehow, have this scenario, where A.N inherits code from A with this code example?
The reason for setting it up like this, is that I need multiple classes that inherit from Base<TType> and the Nested : Base<TType> where the server has the base only, and the client has the extended Nested. This way, it would be easy to use the code, where they would have some shared code between themselves & each other.
The problem is that I would have to write identical code inside the
A and A.N
B and B.N
C and C.N
etc.
I have solved this temporarily, by replacing the Nested abstract class, with an Interface and doing
A.N : A, INested, but now I have to rewrite the Base<TType>.Nested code again inside all the Nested classes. For now, the nested class is small & managable.
hope this isn't a confusing question...
public abstract class Base<TType> where TType : class
{
public TType data;
internal void CommonCodeForAll() { }
public abstract void Update();
public abstract class Nested : Base<TType>
{
public abstract void Input();
}
}
public class A : Base<someClass>
{
public float Somevariable;
public void SpecificFunctionToA() { }
public override void Update()
{
// code that gets executed on server & client side that is unique to A
}
public class N : A.Nested
{
public override void Input()
{
if (data.IsReady()) { Somevariable *= 2; }
SpecificFunctionToA();
}
}
}
public class B : Base<anotherClass>
{
public float Somevariable;
public int index;
public int[] Grid;
public void SomethingElse() { }
public override void Update()
{
// code that gets executed on server & client side that is unique to B
}
public class N : B.Nested
{
public override void Input()
{
if (Grid[index] == -1) { SomethingElse(); }
data.Somevariable = Grid[index];
}
}
}
Edit:
I updated the code example to show what I'm trying to achieve.
Why I am trying to do this, is to keep the physics, networking & User input seperate.
There are multiple different controllers where each one has their own pack & unpacking functions, controller identity & access to the physics engine.
I have a solution using ecapsulation of classes instead of inheritance.
public abstract class BaseGeneric<T>
{
T data;
// ctor
protected BaseGeneric(T data)
{
this.data=data;
}
// methods
public abstract void Update();
// properties
public T Data
{
get { return data; }
set { data=value; }
}
// base nested class
public abstract class BaseNested<B> where B : BaseGeneric<T>
{
protected B #base;
// ctor
protected BaseNested(B #base)
{
this.#base=#base;
}
// methods
public abstract void Input(T data);
public void Update() { #base.Update(); }
// properties
public T Data
{
get { return #base.data; }
set { #base.data=value; }
}
}
}
// implementation base
public class Base : BaseGeneric<int>
{
// ctor
protected Base(int data) : base(data) { }
//methods
public override void Update()
{
this.Data+=1;
}
// implemented nested class
public class Nested : Base.BaseNested<Base>
{
// ctor
public Nested(int data) : base(new Base(data)) { }
public Nested(Base #base) : base(#base) { }
// methods
public override void Input(int data)
{
this.Data=data;
}
}
}
class Program
{
static void Main(string[] args)
{
// new implemented class with value 0
var nested=new Base.Nested(0);
// set value to 100
nested.Input(100);
// call update as implemented by `Base`.
nested.Update();
}
}