States aren't bad, especially for this level of "abstraction" - I actually use them in a few of my scripts. There was a redundancy concern but I don't see that in your original concern you posted above.
The only recommendation I have is to not return a null in your getState(), use something like "State.IDLE" - this will save you at some point! Now if your script was bigger, like if it had tanning support, perhaps "Tasks" would be better than states. If you had less, perhaps no banking at all, I'd suggest removing your states and just including everything in your onLoop.
Just remember the more you abstract, the more the computer has to work. In your implementation, there's no performance concern at all.
For the answer to your question, as others have stated, you need to get an NPC in your onLoop. Think about this logically.
Cow = getclosest("Cow");
Cow = alive
Player->Attack(Cow);
Cow = dead
Player->Attack(Cow); // ERROR: Cow doesnt exist
You must now get a new closest cow.
Now to remove this "redundancy" by searching for a new cow in both the getState() and onLoop(), think about it more logically (again). How about you combine the attack/search state?
If your inventory isnt full, you're not animating, and you're in the cow pen, return State.ATTACK.
In your attack state code, here you can implement searching for the cow and attacking it.