问题
I have written an if else condition which makes use of if not(!) to throw an error. However, the condition does not behave how I had expected and the error gets thrown regardless of who is the currentUser:
public void findCorrectUserRole() {
if (Book.name.equals("Test Answers")) {
User currentUser = User.getCurrentUser()
if (currentUser) {
if (!currentUser.hasUserRole("Teacher") || !currentUser.hasUserRole("System Administrator")) {
throw new LCEX("Sorry, only a teacher or System Administrator can edit this.");
}
}
}else{
"Do Something Else"
}
}
回答1:
Your if condition is wrong it should be:
if (!currentUser.hasUserRole("Teacher") && !currentUser.hasUserRole("System Administrator")) {
throw new LCEX("Sorry, only a teacher or System Administrator can edit this.");
}
or
if (!(currentUser.hasUserRole("Teacher") || currentUser.hasUserRole("System Administrator"))) {
throw new LCEX("Sorry, only a teacher or System Administrator can edit this.");
}
right now if the currentUser role is "teacher", he is not a "system administrator" so the if condition would be true.
回答2:
You're making an invalid assumption that the logical not operator works with logical operations the same way as negative signs work in algebra. There is a rule called DeMorgan's Law that will help you transform logical expressions safely.
As your code is written there is only one way for a user to avoid getting this exception, the user has to have the roles of both teacher and sysadmin:
groovy:000> a = true; b = false; !a || !b // only one is true -> true
===> true
groovy:000> a = b = false; !a || !b // neither is true -> true
===> true
groovy:000> a = b = true; !a || !b // both are true -> false
===> false
This may be clearer if it's rewritten using DeMorgan's law (bringing the negation out from inside the parens means the operator has to change from ||
to &&
); your code is equivalent to this:
if (!(currentUser.hasUserRole("Teacher")
&& currentUser.hasUserRole("System Administrator"))) {
"It is not the case that the current user has both the teacher role and the sysadmin role"
which is definitely not what you want. What you want instead is
if (!currentUser.hasUserRole("Teacher")
&& !currentUser.hasUserRole("System Administrator")) {
"the current user does not have the role of teacher and does not have the role of sysadmin"
Equivalently you could write it as
if (!(currentUser.hasRole("Teacher")
|| currentUser.hasRole("System Administrator"))) {
"it is not the case that the current user has the role of either teacher or sysadmin"
DeMorgan's Law is:
"not (A and B)" is the same as "(not A) or (not B)"
"not (A or B)" is the same as "(not A) and (not B)".
来源:https://stackoverflow.com/questions/30462619/if-not-condition-doesnt-work-as-expected