I have a base class with a method. I want to force all children of this class to call this base method somewhere in their code.
public class BaseClass
{
public void BaseMethod()
{
//Do something
}
}
public class ChildClass1 : BaseClass
{
public void ChildMethod()
{
BaseMethod();
}
}
public class ChildClass2 : BaseClass
{
public void ChildMethod()
{
//Doesn't call BaseMethod();
}
}
So I want ChildClass1 to be fine, but I want ChildClass2 to throw an error.
The reason I want to do this is because my base class has a value that I don't want to forget to implement in my child class. For example, if I am making a bunch of enemies for a game, and the Enemy class has a speed modifier, I don't want to forget to include that in all of the children methods:
public class Enemy
{
public float x;
public float y;
private float speed;
public float GetSpeed()
{
return speed;
}
public void SetSpeed(float speed)
{
this.speed = speed;
}
}
public class Goomba : Enemy
{
public void Move()
{
x += 5 * GetSpeed();
}
}
public class Turtle: Enemy
{
public void Jump()
{
y += 5; //This is wrong. I forgot to adjust for speed.
//y += 5 * GetSpeed(); This is what I want to force myself to do
}
}
Although it is not actually for movement. This is an oversimplification. The base class contains ability modifiers, where the children class are unique abilities that use the modifiers.
How can I structure my code such that a child is required to call a specific parent method somewhere in the code?
You can use the TemplateMethod design pattern
public class BaseClass
{
public void BaseMethod()
{
DoSomething();
TemplateMethod();
}
protected abstract void TemplateMethod();
}
So you make your derived classes implement the template method, but clients of that class call the BaseMethod method. This forces the DoSomething() bit to execute but allows the derived classes to include their own logic.
So a simple example in the case of enemy (obvs adapt so it meets your needs).
public abstract class Enemy
{
public float x;
public float y;
private float speed;
public float GetSpeed()
{
return speed;
}
public void SetSpeed(float speed)
{
this.speed = speed;
}
public void Move()
{
x += GetMovementAmount() * GetSpeed();
}
public abstract decimal GetMovementAmount();
}
public class Goomba : Enemy
{
public void GetMovementAmount()
{
return 5;
}
}
public class Turtle: Enemy
{
public void GetMovementAmount()
{
return 6;
}
}
You could rearrange the code so that changing the position is possible only in base class:
public class Enemy
{
public float x { get; private set; }
public float y { get; private set; }
private float speed;
public Move(float dx, float dy)
{
x += dx * speed;
y += dy * speed;
}
}
Create a new class ability. It will allow you to control what happens when it is run and the user gets to make the run do whatever they want.
public class Ability
{
Action myAct { get; set; }
public Ability(Action inAct)
{
myAct = inAct;
}
public Run()
{
DoStuffBefore();
myAct();
DoStuffAfter();
}
}
Related
I have a problem,
I have 3 classes, one is a base class from which two other inherit,
the base class has a method with a counter,
if the time runs out it should destroy gameObject,
but other classes should have this method but in this conditional statement you could was to add anything
I just want to add an extra command to if from another class.
If you don't understand, feel free to ask, because I'm not good at explaining.
public class A : MonoBehaviour
{
public virtual void DestroyByTime()
{
timeLeft -= Time.deltaTime;
if (timeLeft <= 0)
{
/*
This statement should only be added in class B
|
v
gameSession.GameOver();
*/
Destroy(gameObject);
}
}
private void Update()
{
DestroyByTime();
}
}
public class B : A
{
public override void DestroyByTime()
{
/*
I want the base class if to be saved, but in if statement time runs out you lose
(gameSession.GameOver())
*/
}
}
You can create an OnTimeOut method an override only in derived class:
public class A : MonoBehaviour
{
public virtual void DestroyByTime()
{
timeLeft -= Time.deltaTime;
if (timeLeft <= 0)
{
OnTimeOut();
Destroy(gameObject);
}
}
protected virtual void OnTimeOut()
{
// Do nothing here
}
private void Update()
{
DestroyByTime();
}
}
public class B : A
{
protected override void OnTimeOut()
{
gameSession.GameOver();
}
}
I have a quesition.
Is in this example did i asue correctly design pattern - decorator?
I want to increase speed of plane after decorate.
Does decorator always has to add new methods? Can only overwrite existing methods?
This is IPlane interface:
interface IPlane
{
void MoveLeft();
void MoveRight();
Rectangle GetPlaneBody();
int GetHealthPoints();
int GetSpeed();
Bullet Shot();
void SetSpeed(int speed);
}
This is plane class:
public class Plane : IPlane
{
private Rectangle PlaneBody = new Rectangle();
private int HealthPoint;
private int x=200;
private int speed;
private Bullet Amunition = new Bullet();
private static Plane instance;
private Plane() { }
public static Plane Instance
{
get
{
if (instance == null)
{
instance = new Plane();
instance.PlaneBody.Height = 125;
instance.PlaneBody.Width = 115;
instance.PlaneBody.X = 200;
instance.PlaneBody.Y =600;
instance.HealthPoint = 1000;
instance.speed = 10;
}
return instance;
}
}
public void MoveLeft()
{
if(x>-10)
x -= speed;
PlaneBody.X = x;
}
public void MoveRight()
{
if(x<1165)
x += speed;
PlaneBody.X = x;
}
public Rectangle GetPlaneBody()
{
return PlaneBody;
}
public int GetHealthPoints()
{
return HealthPoint;
}
public int GetSpeed()
{
return speed;
}
public Bullet Shot()
{
Bullet bullet = new Bullet();
bullet.SetDamage(Amunition.GetDamage());
bullet.SetSpeed(Amunition.GetSpeed());
bullet.SetCoordinates(x+10, this.PlaneBody.Y - 30);
return bullet;
}
public void SetSpeed( int speed)
{
this.speed = speed;
}
}
This is abstract decorator:
class AbstractPlaneDecorator : IPlane
{
protected IPlane plane;
public AbstractPlaneDecorator(IPlane plane)
{
this.plane = plane;
}
public int GetHealthPoints()
{
return plane.GetHealthPoints();
}
public Rectangle GetPlaneBody()
{
return plane.GetPlaneBody();
}
public int GetSpeed()
{
return plane.GetSpeed();
}
public virtual void MoveLeft()
{
plane.MoveLeft();
}
public virtual void MoveRight()
{
plane.MoveRight();
}
public void SetSpeed(int speed)
{
plane.SetSpeed(speed);
}
public Bullet Shot()
{
return plane.Shot();
}
}
And concrete decorator:
class IncreaseSpeedDecorator : AbstractPlaneDecorator
{
public IncreaseSpeedDecorator(IPlane plane) : base(plane)
{
}
public override void MoveLeft()
{
plane.MoveLeft(); // move two times faster
plane.MoveLeft();
}
public override void MoveRight()
{
plane.MoveRight(); // move two times faster
plane.MoveRight();
}
}
This decorator makes that plane moves 2 times faster (He performs the same method twice). Does it meet the rules of decorator pattern?
I would say the implementation is fine.
I don't know the exact context of your code, but it might be a bit strange that if you ask your decorator for the plane's speed, it will return the plane's base speed, but the plane is moving twice as fast. I think a better name for the decorator to describe its funcionality would be DoubleMoveDecorator or something like that, since it doesn't actually do anything with the plane's speed.
for example we have class Foo
class Foo {
public class Physics {
float gravity = 9.8f;
float seperateDistance = 10f;
}
public Physics physics;
void Start(){
physics = new Physics();
Bar baz = AddComponent<Bar>();
}
}
Meanwhile, in Bar component, we are trying to get the gravity value inside Foo's physics.
Currently this is the only way I can think of. which i somehow feel not good about. If class Foo is removed then Bar will not working anymore, which i guess is not a good practice.
Inside the baz we created in Foo:
void Start(){
//...
float gravity = getComponent<Foo>().physics.gravity;
//...
}
Is there any better ways to do this?
If I'm reading you correctly, the issue that you're worried about is class coupling. As Georg's answer said, you should be using properties, not fields. But you can avoid class coupling by injecting an interface into Bar that Foo implements. This means that you don't need a Foo to code Bar:
public interface IGravitySource
{
double Gravity { get; }
}
public sealed class Foo : IGravitySource
{
private readonly Physics myPrivatePhysics = new Physics();
private sealed class Physics
{
public double Gravity { get; } = 9.81;
public double Smoothness { get; } = 0.05;
}
public double Gravity => myPrivatePhysics.Gravity;
}
public sealed class Bar
{
private readonly IGravitySource gravitySource;
public Bar(IGravitySource gravitySource)
{
this.gravitySource = gravitySource;
}
public void Start()
{
//...
var gravity = gravitySource.Gravity;
gravity += 1;
//...
}
}
EDIT:
Technically, you might be introducing debt by effectively re-implementing the properties of IGravitySource in multiple places. One solution to this is to have the IGravitySource only have a single member, IGravity. This way, if you decide to extend IGravity with direction, you don't need to change the implementation of Foo:
public interface IGravitySource
{
IGravity Gravity { get; }
}
internal interface IGravity
{
double AccelerationDueToGravity { get; }
}
public sealed class Foo : IGravitySource
{
private readonly Physics myPrivatePhysics = new Physics();
private sealed class Physics : IGravity
{
public double AccelerationDueToGravity { get; } = 9.81;
public double Smoothness { get; } = 0.05;
}
public IGravity Gravity => myPrivatePhysics;
}
public sealed class Bar
{
private readonly IGravitySource gravitySource;
public Bar(IGravitySource gravitySource)
{
this.gravitySource = gravitySource;
}
public void Start()
{
//...
var gravity = gravitySource.Gravity.AccelerationDueToGravity;
gravity += 1;
//...
}
}
This is usually done through properties which are basically pairs of two methods, a getter and setter method.
To use them, just exchange public Physics physics; by public Physics physics { get; set; }. There is no need to change the consuming code since properties are accessed like fields in C#. However, properties also allow you to customize the getter and setter. The good thing is that such a modification is transparent to client code, so you can change the access to that property without having to change code that consumes the property. Further, properties can be virtual or abstract and are allowed to be part of an interface.
You can check if there's a Foo component attached
void Start() {
//Check if there's Foo, if no then give them default to 3;
float gravity = GetComponent<Foo>() ? GetComponent<Foo>().physics.gravity : 3;
//...
}
Or you can also add RequireComponentAttribute to the class Bar, so that Foo will always tied to Bar RequireComponentAttribute
But if you mean 'what if Foo Class(not component) doesn't exist anymore.
I suggest you to do Method Injection like Adam Brown answers.
But there's another solution when class is no longer exist.
here's my thought.
Create a special Attribute to detemine which field is shareable. and then get the field wh use that Attribute.
Example :
of course this isn't tested yet, but by theory it will work.
//Some special attribute
[AttributeUsage(AttributeTargets.Field)]
public class ShareFieldAttribute : Attribute {
}
class Foo {
public class Physics {
float gravity = 9.8f;
float seperateDistance = 10f;
}
//mark ShareField attribute to this field
[ShareField]
public Physics physics;
void Start(){
physics = new Physics();
Bar baz = AddComponent<Bar>();
}
}
class Bar {
void Start() {
//Get the field 'public Physics physics' by name and Type
Physics physics = GetShareField<Physics>("physics", null);
float gravity = physics ? physics.gravity : 3;
//...
}
//Method Helper
public T GetShareField<T>(string fieldName, T defaultValue)
{
foreach(var c in GetComponents<MonoBehaviour>())
{
var fields = c.GetType().GetFields().Where(field => field.FieldType == T && field.Name == fieldName && field.IsDefined(typeof(ShareFieldAttribute), false));
return (T)fields[0].GetValue(c);
}
return defaultValue;
}
}
Guys I was working on Unity3D's MonoDevelop. I was implementing my classes however I got an error I cannot figure out what is. The problem I get is in the title at the line where I override the abstract methods proceed and isFinished. What is the problem?
namespace tool
{
public class TaskManager
{
public TaskManager ()
{
}
}
public abstract class Task {
public bool isEvitable = true;
public abstract void proceed();
public abstract bool isFinished();
}
public class MoveTask : Task {
float speed;
Vector3 targetPosition;
GameObject movingObject;
private MoveTask(GameObject gameObject, float speed, Vector3 target) {
this.movingObject = gameObject;
this.speed = speed;
this.targetPosition = target;
}
#override
public void proceed() {
Vector3 objPos = movingObject.transform.position;
movingObject.transform.position = new Vector3 (Mathf.Lerp(objPos.x, targetPosition.x, speed),
Mathf.Lerp(objPos.y, targetPosition.y, speed),
Mathf.Lerp(objPos.z, targetPosition.z, speed));
}
#override
public bool isFinished() {
}
}
}
try this. yours is java syntax.
public override void proceed(){
}
public override bool isFinished(){
return false;
}
how about this?
public partial class Form1 : Form
{
ExploitAPI api ; new ExploitAPI
public ExploitAPI Api { get => api; set => api = value; }
public Form1()
{
InitializeComponent();
api.LaunchExploit();
}
private void Button1_Click(object sender, EventArgs e)
{
api.ToggleClickTeleport();
}
}
}
please answer the fix as soon as possible
Best regards, guest
Weird question here. I have a main class which manages a bunch of event classes...I want one of the events to alter a value in the main class.
Normally, I would do something like this by using the ref keyword...but in this case, I want to pass in the reference in the constructor, and have any further modifications by the class be reflected in the main class. Is this possible? Right now I have the following:
class MainClass {
float transparency = 0.0f;
List<Events> listOfEvents;
listOfEvents.Add(new FadeInEvent(ref float transparency));
}
class FadeInEvent {
float transparency;
public FadeInEvent(ref float t) {
transparency = t;
}
public void Update() //Occurs every frame
{
transparency += 0.01f;
}
}
This does not work; the transparency in the main class is not updated by the FadeInEvent class. How can I work this out?
How about creating a class for the variable as classes are pass by reference automatically:
class Transparency
{
public float Value = 0.0f;
}
class MainClass
{
Transparency transparency = new Transparency();
// this List<Events> doesn't match class, but I'm sure this was just a sample of a larger problem
List<Events> listOfEvents = new List<Events>();
listOfEvents.Add(new FadeInEvent(transparency));
}
class FadeInEvent{
Transparency transparency;
public FadeInEvent(Transparency t) {
transparency = t;
}
public void Update() //Occurs every frame
{
transparency.Value += 0.01f;
}
}
You cannot keep a reference to a value type, such as float. What you can do is have a FadeInEvent constructor that takes a MainClass and modify it's public Transparency property:
class MainClass
{
float transparency = 0.0f;
public float Transparency
{
get { return transparency;}
set { transparency = value;}
}
List<Events> listOfEvents;
public void AddFadeInEvent()
{
listOfEvents.Add(new FadeInEvent(this));
}
}
class FadeInEvent
{
MainClass mainClass;
public FadeInEvent(MainClass mainClass)
{
this.mainClass = mainClass;
}
public void Update() //Occurs every frame
{
mainClass.Transparency += 0.01f;
}
}