When overriding a method, only the offending that has been defined in the underlying class version of the method is generated. This is an important limitation because it means that code that works with the underlying class is automatically applied to any object derived from the underlying class (which, of course, is the basic OOP concept), including the violation.
The following example shows the type of restriction imposed on the violation (at compile time):
: Stormyinning.java//overridden methods may throw only the//exceptions specified in their Base-class//versions,
or exceptions derived from the//Base-class exceptions. Class Baseballexception extends Exception {} class foul extends Baseballexception {} class Strike extends n {} Abstract class inning {inning () throws baseballexception {} void Event () throws Baseballexception {//Does
N ' t actually have to throw anything} abstract void Atbat () throws Strike, foul; void Walk () {}//Throws Nothing} class Stormexception extends Exception {} class Rainedout extends Stormexception {} cl
Ass Popfoul extends Foul {} interface Storm {void event () throws Rainedout;
void Rainhard () throws Rainedout; } public class Stormyinning extends inning implements Storm {//OK to add new exceptions for constructors,//b
UT you must deal with the base constructor//Exceptions:stormyinning () throws Rainedout, Baseballexception {} StorMyinning (String s) throws foul, Baseballexception {}//Regular methods must conform to base class://! void Walk () throws Popfoul {}//compile Error//Interface cannot add exceptions to existing//methods from the base Class://! public void event () throws Rainedout {}//If The doesn ' t already exist in the//base class, the exception is ok:public void Rainhard () throws Rainedout {}//can choose to don't throw any exceptions,//even if base Versio n does:public void Event () {}//overridden methods can throw//inherited exceptions:void Atbat () throws POPFO
UL {} public static void Main (string[] args) {try {stormyinning si = new stormyinning ();
Si.atbat (); catch (Popfoul e) {} catch (Rainedout e) {} catch (Baseballexception e) {}//Strike not thrown in derived ve
Rsion.
try {//What happens if you upcast?
inning i = new stormyinning ();
I.atbat (); You must catch the ExceptiONS from//Base-class version of the method: catch (Strike e) {} catch (Foul e) {} catch (Rainedou T e) {} catch (Baseballexception e) {}}}///:~
In inning, you can see that both the builder and the event () method indicate that they are "throwing" a violation, but they do not actually do that. This is legal because it allows us to force the user to capture any violations that may have been added in the overwritten event () version. The same applies to the abstract method, as it is shown in Atbat ().
"Interface Storm" is interesting because it contains a method defined in incoming,--event (), and a method that is not defined therein. Both of these methods will "throw" a new type of violation: Rainedout. When you perform to "stormyinning extends" and "Implements Storm", you can see that the event () method in Storm cannot change the offending interface of event () in inning. In the same way, this design is very reasonable, otherwise, when we operate the base class, we simply do not know what we capture the right things. Of course, if one of the methods defined in interface is not in the underlying class, such as Rainhard (), it is not a problem when it comes to offending.
The restriction on the violation does not apply to the builder. In stormyinning, we can see that a builder can "throw" anything it wants, regardless of what the underlying class builder "throws". However, the derived class builder must declare all the underlying class builder violations in its own offending specification, because the underlying class builder must be persisted in some way (where the default builder is invoked automatically).
Stormyinning.walk () does not compile because it "throws" a violation, while Inning.walk () does not "throw" it. Allowing this to happen allows your code to call Inning.walk (), and it does not have to control any violations. However, when you later replace an object from a class derived from inning, the violation is "tossed", causing the execution of the code to break. The substitution of objects can be consistent by forcing the derived-class approach to comply with the offending specification of the underlying class method.
The overridden event () method shows us that a derived class version of a method can produce no violation-even if the underlying class version is to be breached. Likewise, this is necessary because it does not break code that has assumed that the underlying class version would have caused the violation. The same applies to Atbat (), which will "throw" a popfoul--from the foul, and the foul violation is generated by the base class version of Atbat (). Thus, if someone operates inning in their own code and calls Atbat (), the foul violation must be captured. Because Popfoul is derived from foul, the offending controller (module) also captures Popfoul.
The last interesting place is inside main (). In this place, if we explicitly operate on a Stormyinning object, the compiler forces us to capture only those violations that are specific to that class. But if we go back to the base type, the compiler forces us to catch the violation of the underlying class. With all these restrictions, the "robust" level of the offending control code has been significantly improved (note ③).
③:ansi/iso C + + imposes similar restrictions, requiring that the derivative methods be the same or derived from the underlying class method. In this case, C + + can actually check the offending specification during compilation.
We must recognize this: While the violation rules are enforced by the compiler during inheritance, the offending specification is not part of the method type, which only includes the method name and the argument type. Therefore, we should not cover the method on the basis of the offending code. In addition, although an offending specification exists in the underlying class version of a method, it does not imply that it must exist in the derived class version of the method. This is quite different from the "inheritance" of a method (when inheriting, the methods in the underlying class must also exist in the derived class). In other words, the "offending specification interface" for a particular method may become narrower when inheriting and overwriting, but it will not become more "wide"-which is exactly the opposite of the class interface rule when inheriting.