If not condition doesn't work as expected

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-11 03:33:55

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!