Enum with functions? - java

I saw the page:
I'm familiar with this SO question for creating enums in Python. However, I can't find an example anywhere of an enum that has functions.
I'm mainly a Java programmer.
I wrote this code in Java:
public enum Role {
SOLDIER(4),
DEMOMAN(2),
SCOUT(4),
MEDIC(2);
private final int maxPlayers;
private Role(int maxPlayers) {
this.maxPlayers = maxPlayers;
}
public int getMaxPlayers() { return maxPlayers; }
}
I tried to do the same in Python:
class Klass:
SCOUT = 1
SOLDIER = 2
DEMOMAN = 3
MEDIC = 4
#staticmethod
def maxPlayers(klass):
return {
Klass.SCOUT : 4,
Klass.SOLDIER : 4,
Klass.DEMOMAN : 2,
Klass.MEDIC : 2,
}[klass]
For some reason. I feel like I'm doing it wrong.
What is the best practice for associating functions to enums in Python?
I don't actually care if the suggested answer doesn't use an enum; I'm just trying to understand the best practice for implementing the above Java code in Python.
I'm willing to use this enum in the following:
class Players(dict):
def countKlass(self, klass):
count = len(filter(lambda x: x == klass, self.values()))
return count

Let's remember what enums in Java really are -- static final instances of a class. All they really are is just named constants.
Generally, python favors a looser (or if you prefer, more flexible) coding style than Java. Part of that is that there's no such thing as a constant, and part of it is trusting users of your code not to do crazy things. In that vein, you can get a similar effect to your java code by doing this:
class Role(object):
class RoleType(object):
def __init__(self, maxPlayers):
self.maxPlayers = maxPlayers
SOLDIER = RoleType(4)
DEMOMAN = RoleType(2)
SCOUT = RoleType(4)
MEDIC = RoleType(2)
Then you can access them like this
s = Role.SOLDIER
print s.maxPlayers # Prints 4
What this doesn't do is prevent users of your library from creating new roles. Doing so is slightly awkward, though, which should be a hint to the user that "they're doing it wrong".
newRole = Role.RoleType(22) # as an example
If you go this route, you just more or less have to live with that. If you favor using convention though, this generally won't be a problem. They can always just access the values you've defined.

If you are looking for best practices, typically you'd just make a dictionary.
klass = {'SCOUT':4,
'SOLDIER':4,
'DEMOMAN':2,
'MEDIC':2,}
print klass['MEDIC']
2
If you want this to be a class method you could say:
class Klass:
def maxPlayers(self, klass):
return {'SCOUT':4,
'SOLDIER':4,
'DEMOMAN':2,
'MEDIC':2,}[klass]
This is how you'd use it:
print Klass().maxPlayers('MEDIC')
2

Using the AutoEnum recipe, your code could look like this:
class Role(AutoEnum):
SCOUT = 4
SOLDIER = 4
DEMOMAN = 2
MEDIC = 2
def __init__(self, max_players):
self.max_players = max_players
And now you have the benefits of the new Python Enum (backported if you don't have 3.4):
--> Role.SCOUT
<Role.SCOUT: 3>
--> Role.SCOUT.max_players
4

Related

Kotlin accessing variable from other class not by name directly but by string variable

I'm trying to access a variable from another class. The usual way would be:
in Class A
var something = ClassB().element
in Class B
val element = "hi"
Is it also possible to address element not by its name directly, but when I have the name stored in a string? So I have a string that holds
var name = "element"
and want to do something like
var something = ClassB().name //(this doesn't work)
The reason I'm asking is because I have a class in which I do some pitch processing and another class in which I store all of my pitch data in float arrays (the Hz values of different musical notes for different tunings of different instruments)
In the class I do my pitchprocessing in I want to select the right float array depending on a user selection (made with a spinner), which I "translate" with a map (so for example the spinner says "Standard Tuning" and the according array would be called "guitarStandard", in my map "Standard Tuning" would be the key and "guitarStandard" the according value). To not hardcode the different cases in which I need different arrays with if statements, I simply want the name of the array stored in a string by getting the correct value of my map and adress it that way.
I feel like that should be either super simpel or I'm thinking about it the completely wrong way, can someone help out? Thanks
I would advise that you don't store a list of strings, and instead store a list of lambdas that return property values:
class Foo {
val prop1 = arrayOf(1.0, 2.0, 3.0)
val prop2 = arrayOf(4.0, 5.0, 6.0)
}
fun main() {
val props: List<(Foo) -> Array<Double>> = listOf({it.prop1}, {it.prop2})
val foo = Foo()
for (prop in props) {
println(prop(foo).toList())
}
}
But, if you wanted to search up property names from a string, you should look into reflection.
I'd suggest to refactor your ClassB by extracting those properties to separate enum class:
enum class Tunes(vararg f: Float) {
TUNE1(1.0f, 2.0f, 3.0f), TUNE2(4.0f, 5.0f, 6.0f);
val frequencies: FloatArray = f
}
That will make your mapping more straightforward and won't involve reflection:
import Tunes.*
val mapping = mapOf("Standard Tuning" to TUNE1, "Alternate Tuning" to TUNE2)
val result = mapping[userInput]?.frequencies

Is it an overhead to use #Builder(toBuilder = true) instead of setters?

I always strive to make my code fully immutable and not utilize setters at all.
When I need to update an object, dto or entity I use #Builder(toBuilder = true) instead of setters.
public Car updateCar(final String id) {
final Car existing = carRepository.getById(id);
final Car.CarBuilder builder = existing.toBuilder().make("Mercedes-Benz");
if (anyCondition) {
builder.status("READY");
}
final Car updatedCar = builder.build();
return carRepository.save(updatedCar);
}
I would like to ask you is it really bad from a performance perspective that instead of setting a value into an already instantiated object, I create a new one?
Maybe in the above piece of code, it's not significant but I also may require to change one field in all objects in a collection thus the space complexity would be linear.
What approach do you prefer: setters or toBuilder?
P.S.: the code snippet above is just for better understanding of how I utilize toBuilder
I would like to ask you is it really bad from a performance
perspective that instead of setting a value into an already
instantiated object, I create a new one?
You're asking us, and yourself, the wrong question.
You shouldn't really be concerned about performance for such simple, data-carrier, classes.
Benchmark (see JMH) and see.
But from a purely theoretical standpoint, the only overhead is the creation of another object (which size in memory depends on its members' layout), the additional step of transferring the primitive values/references from the builder instance to the resulting instance (maybe also more work for the GC? I wouldn't even consider that).
Thus some more CPU cycles.
Look also at Immutables, look at how many people and companies are using it, and ask yourself if for your simple usecases you should really consider asking this question.
Take this class
public class Car {
private String maker;
private int year;
private int kms;
// Getter - setters
}
The size is approximately 16 + 4 + 4 + 4 = 28 bytes.
Now, using a builder such as
public class CarBuilder {
private String maker;
private int year;
private int kms;
public CarBuilder setMaker(final String maker) {
this.maker = maker;
return this;
}
public CarBuilder setYear(final int year) {
this.year = year;
return this;
}
public CarBuilder setKms(final int kms) {
this.kms = kms;
return this;
}
public Car createCar() {
return new Car(maker, year, kms);
}
}
The size is still approximately 16 + 4 + 4 + 4 = 28 bytes.
That means you'll have at least doubled the bytes used in the heap for just the class using a builder.
However, what you need to think about is Java being reference-based. That means all the created objects' pointers will simply be copied to the produced Car instance. The objects will still be unique in memory.
After your edit, maybe what you're trying to do is Object Pooling?
In that case, consider Apache Commons Pool.

What design patterns are available for Data Classes in Java?

I have a complex class in Java whose responsibility it to mainly store Data. I was wondering if there are any design patterns available to guide such use cases.
To be more specific, the class is something which records the overall performance of a student per semester.
Class StudentReport{
cgpa = 3.1;
Set <SubjectReport> perSubjectReportSet;
overallFeedback = "..."
...
}
Class SubjectReport{
subjectName = "Subject_A";
gpa = 2.4;
// Test Details
test = Pass;
testQuestionAnsweredCount = 8;
testQuestionsCount = 10;
testFeedback = None; // Feedback if FAIL
// Assignment Details
assignment = Pass;
...
//Exam Details
finalExam = Fail;
examQuestionAnsweredCount = 5;
examCorrectlyAnsweredQuestionCount = 2;
examQuestionsCount = 10;
examFeedback = "Blah Blah OOP" // Feedback if FAIL
}
A design pattern to encapsulate class attributes, is the private class data pattern. It seeks to reduce the visibility of the class attributes
The description: "I have a complex class in Java whose responsibility it to mainly store Data" is a bit to general, does not every object store data combined with behavior?
You're example code does show a design: the composition pattern.

How do I write a hint for Netbeans?

I have looked everywhere, and the only example I could find was one for marking JOptionPane.show and removing it. That doesn't help me much.
Note: This goes over making a hint that will match a method, but when you are done, you should be able to match more (like learning RegEx)
This was rather difficult to do and figure out... I am going to assume you have gone over the tutorial at https://platform.netbeans.org/tutorials/nbm-java-hint.html. After creating the hint via the instructions there, you now have a basic Hint implementation:
#Hint(displayName = "#DN_MainCallHint", description = "#DESC_MainCallHint",
category = "general")
#Messages({
"DN_MainCallHint=MainCall",
"DESC_MainCallHint=Warns the user when they are manually calling public "
+ "static void main"
})
public class MainCallHint {
#TriggerPattern(value = "$str.equals(\"\")", //Specify a pattern as needed
constraints = #ConstraintVariableType(variable = "$str", type
= "java.lang.String"))
#Messages("ERR_MainCallHint=Directly calling main! Did you mean to do that?")
public static ErrorDescription computeWarning(HintContext ctx) {
return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.
ERR_MainCallHint());
}
}
The main trouble I had was with #TriggerPattern.value. If you wanted to match a method call, you would set it to something like this:
"$caller.method($arg1, $arg2)"
and can set type constraints for each of those variables. One important thing to note: if you are trying to match a static method of a particular type, use the FQN of that class or it won't work with arguments. So use something like this:
"test.HintTest.main($args)"
Resulting in the #TriggerPattern bit to look like this:
#TriggerPattern(value = "test.HintTest.main($args)", //Specify a pattern as needed
constraints = #ConstraintVariableType(variable = "$args", type
= "java.lang.String[]"))
And you get this:
Now, the tutorial shows a very cumbersome way to implement a fix. If all you need to do is a simple replace, then it can be done like this:
public static ErrorDescription computeWarning(HintContext ctx) {
Fix fix = JavaFixUtilities.rewriteFix(ctx, "Use notMain instead",
ctx.getPath(), "test.HintTest.notMain($args)");
return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.
ERR_MainCallHint(), fix);
}
Note: The variables used for rewriteFix must be the same you used in #TriggerPattern or they will be interpreted as literals.

public class member in scala class not accessible in java class

I'm learning scala, and to practice, I have started to convert some of my existing java classes into scala, so I can also learn about scala-java inter-op. Following is my project setup:
Scala class :
#Entity
class DemoBeanScala{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#BeanProperty
var Id: Long= _
#BeanProperty
var str: String= _
#BeanProperty
var num: Int = _
#BeanProperty
var d:Double = _
def testFunc(printText: () => Unit){
printText()
}
val pr = () => {
println("functional programming test")
}
}
Java class(extract):
#RequestMapping("/demo")
public DemoBeanScala demo(#RequestParam(value="id") Long Id, #RequestParam(value="str") String str, #RequestParam(value="num") int num, #RequestParam(value="d") double d)
{
DemoBeanScala dbs = new DemoBeanScala();
dbs.setId(123456);
dbs.setStr("sample text");
dbs.setNum(1);
dbs.setD(2.1);
dbs.testFunc(dbs.pr);
return dbs;
}
From what I have learnt, pr in DemoBeanScala class should be accessible in my java class, since no modifier is declared before it. But, after maven compilation(using scala:compile) and running java code, I'm getting an error saying that pr is private in DemoBeanScala class. What am I doing wrong?
If you look at your compiled class in javap, you will see somethign like this :
public class DemoBeanScala {
private final scala.Function0<scala.runtime.BoxedUnit> pr;
public scala.Function0<scala.runtime.BoxedUnit> pr();
// And some other stuff...
}
You will notice two important difference with Java :
Scala respects the uniform access principle, so there is no difference between calling a method without a parameter list or accessing a property. To make that work, the scala compiler will generate a public accessor method and a private field to represent a public property.
Java doesn't have methods without a parameter list: they always have at least an empty parameter list.
So, from Java, you need to access the pr property with dbs.pr(), not dbs.pr (or generate a Java-style getter with #BeanProperty, as you did for your other properties, and access it as dbs.getPr()).
When you add #BeanProperty that particular property is not visible in java class, only the generated public setters and getters are available or you may access scala like setter (pr_$eq()) and getter (pr()).
I could not find a proper reference, but the following links may helpful for you, they are not directly related to this question, but they will help you understanding.
Scala: Can I declare a public field that will not generate getters and setters when compiled?
https://issues.scala-lang.org/browse/SI-4481

Categories

Resources