This article is the 11th day article of StudioZ Tech Advent Calendar 2019.
I started using Unity about 5 years ago and switched from Java to C #. Since it is a language with many similarities, I was able to use it with almost no discomfort, but the only problem was the enum specifications. So I wondered if I could reproduce the Java enum in C #.
--The enumerator has an instance of the enum. ――You can meet it by using the class normally --Cannot create an instance from the outside --It can be handled by making the constructor private. --Enumeration. Can be accessed by enumeration --If you manage the instance of the enumerator in the static field, it will be accessible. --You cannot define an enumerator with the same name --A field with the same name cannot be defined, so it will be satisfied when managing with a static field.
If you code the conditions so far, it will look like this
public class EnumSample {
public static EnumSample Enum1 = new EnumSample();
public static EnumSample Enum2 = new EnumSample();
public static EnumSample Enum3 = new EnumSample();
public static EnumSample Enum4 = new EnumSample();
//Cannot create an instance from the outside
private EnumSample() {}
}
--The enumerator can have unique values --Receive the value in the constructor and have it in the field --However, you cannot statically check for duplicates (you can check at runtime).
public class EnumSample2 {
public static EnumSample2 Enum1 = new EnumSample2( 1 );
public static EnumSample2 Enum2 = new EnumSample2( 2 );
public static EnumSample2 Enum3 = new EnumSample2( 3 );
public static EnumSample2 Enum4 = new EnumSample2( 4 );
public int Num;
//Cannot create an instance from the outside
private EnumSample2( int num ) {
Num = num;
//If you want to check for duplicates, do it around here
//It seems easy to pack it in a dictionary and check it with the Contains Key
}
}
--Methods can be implemented for each instance --Make the enumerator class an abstract class and inherit the class for each enumerator to implement the method --Abstract if you want to make it mandatory for each enumerator, virtual if you want to define the default behavior --Duplicate processing can be eliminated by implementing the processing that you want to standardize between enumerators on the parent class side and the processing that you want to differentiate on the child class side. --The enumeration can implement the interface --Just declare the interface to be implemented in the enum
//Drop item interface
public interface IDropItem {
string Name { get; }
int Price { get; }
string Description { get; }
}
//Enumeration of weapons that can be treated as drop items
public abstract class Weapon : IDropItem {
public static Weapon Sword = new WeaponSword();
private class WeaponSword : Weapon {
//Even if the constructor is public, the class itself is private, so it cannot be instantiated from the outside.
public WeaponSword() {}
public override string Name { get { return "sword"; } }
public override int Price { get { return 100; } }
public override string Description { get { return "A nice explanation"; } }
public override void Attack() {
base.Slash();
}
}
public static Weapon Spear = new WeaponSpear();
private class WeaponSpear : Weapon {
public WeaponSpear() {}
public override string Name { get { return "spear"; } }
public override int Price { get { return 50; } }
public override string Description { get { return "Explanation like that"; } }
public override void Attack() {
base.Pierce();
}
}
public static Weapon Club = new WeaponClub();
private class WeaponClub : Weapon {
public WeaponClub() {}
public override string Name { get { return "club"; } }
public override int Price { get { return 10; } }
public override string Description { get { return "Very strange explanation"; } }
// Attack()Implementation is optional
}
protected Weapon() {}
//Be sure to define the name, price, and description with an enumerator
public abstract string Name { get; }
public abstract int Price { get; }
public abstract string Description { get; }
//Implementation of attack processing can be omitted
public virtual void Attack() {
//If not overridden, the process of hitting as the default
Strike();
}
//Properties and methods declared as protected can be accessed from the enumerator side
protected void Slash() {
//Processing weapons to cut
}
protected void Pierce() {
//Handling of stabbing weapons
}
protected void Strike() {
//Handling of beating weapons
}
}
--Use enumerator as a switch condition --You can't use enumerators that are actually classes, because you can only use constants in cases ――However, since you can implement the process on the enumerator side, I think that you basically do not need to use switch.
It may seem awkward at first glance, but using Java-style enums makes it easier to achieve polymorphism. If you have a chance, please give it a try
Java constants are Enums! I will tell you how to use Enums and how to think about them
Recommended Posts