import static Helpers320.UtilsIan.*; /* Java-isms to note: * - using a float entails tagging constants as 'f' * - we'll see more on enums: they are currently objects-with-0-fields; * there are exactly 5 CatColors (and we have "enumerated" all 5 of them). * They have a toString. We'll see later versions were we add fields; * you can also add constructors. * In Rust, you can take it further: entire union-types, but still called 'enum's. * - we'll review how 'equals' works */ enum CatColor { BLACK, GREY, ORANGE, CALICO, TORTOISESHELL } class Cat { String name; CatColor color; float clawSharpness; // A number between 0 and 1 (where 1=perfectly sharp). // Update this Cat, after it scratches something; // it may be something that `sharpens` the claws (like a tree), // or something that slightly dulls them (like human flesh). // void scratch( /* Cat this, */ boolean sharpens ) { if (! sharpens) { System.out.printf("Yeeowch!\n"); // presumably using their claws on a person this.clawSharpness -= SHARPENING_FACTOR*this.clawSharpness; } else { // get (say) 25% closer to full sharpness this.clawSharpness += SHARPENING_FACTOR*(1.0f-this.clawSharpness); } // TODO: DRAW MEMORY DIAGRAM, FIRST TIME THIS LINE IS REACHED } // How much scratching might sharpen your claws. // The fraction between current-sharpness and perfect-sharpness (1.0) to improve. // static float SHARPENING_FACTOR = 0.10f; public static void main( String... __ ) { testAll(); } // @Override public String toString( /* Cat this */ ) { return String.format("Cat[name='%s', color=%s, clawSharpness=%4.2g]", this.name, this.color, this.clawSharpness); } // Canonical constructor Cat( String _name, CatColor _color, float _clawSharpness ) { this.name = _name; this.color = _color; this.clawSharpness = _clawSharpness; } // constructor w/ default clawSharpness Cat( String _name, CatColor _color ) { this(_name, _color, 0.50f); } // @Override public boolean equals( /* Cat this, */ Object that ) { return switch (that) { case null -> false; case Cat thatt when this==thatt -> true; // hot path -- not for correctness //case Cat(nm,clr,shrp) -> ... case Cat thatt -> ( this.name.equals(thatt.name) && this.color.equals(thatt.color) && equalsApprox( this.clawSharpness, thatt.clawSharpness ) ); default -> false; // `that` couldn't match `Cat` }; } static void testAll() { assertAssertionsEnabled(); testConstructor(); testToString(); testScratch(); } static void testConstructor() { System.out.printf("Testing constructor: "); // In practice, we might bundle this with tests of toString and equals. // (And if we used `record` instead of `class`, we would't need to!) // making sure our 'equals' works: assertTrue( new Cat( "Bartok", CatColor.BLACK, 0.9f ).equals( new Cat( "Bartok", CatColor.BLACK, 0.9f ) )); assertEquals( new Cat( "Bartok", CatColor.BLACK, 0.9f ), new Cat( "Bartok", CatColor.BLACK, 0.9f ) ); assertFalse( new Cat( "Bartok", CatColor.BLACK, 0.9f ).equals( new Cat( "Garfield", CatColor.ORANGE, 0.5f ) )); // check that default constructor uses 0.50f sharpness: assertEquals( new Cat( "Bartok", CatColor.BLACK), new Cat( "Bartok", CatColor.BLACK, 0.5f ) ); System.out.printf("done.\n"); } static void testToString() { System.out.printf("Testing toString: "); assertEquals( new Cat( "bartok", CatColor.BLACK).toString(), "Cat[name='bartok', color=BLACK, clawSharpness=0.50]" ); assertEquals( new Cat( "pepsi", CatColor.CALICO, 0.1234f).toString(), "Cat[name='pepsi', color=CALICO, clawSharpness=0.12]" ); System.out.printf("done.\n"); } static void testScratch() { System.out.printf("Testing scratch: "); // NOTE tests are tuned for SHARPENING_FACTOR = 0.10; // must re-write some if that changes. Cat bartok = new Cat( "Bartok", CatColor.BLACK, 0.80f ); Cat garfield = new Cat( "Garfield", CatColor.ORANGE, 0.50f ); garfield.scratch(false); assert( garfield.equals(new Cat("Garfield", CatColor.ORANGE, 0.45f) ) ); garfield.scratch(false); assert( garfield.equals(new Cat("Garfield", CatColor.ORANGE, 0.405f) ) ); assert( bartok.equals(new Cat("Bartok", CatColor.BLACK, 0.80f) ) ); // With mutation, testing *includes* checking that we didn't // modify other fields, NOR other fields of other objects // (e.g. that we didn't accidentally declare a field `static`). bartok.scratch(true); assert( bartok.equals(new Cat("Bartok", CatColor.BLACK, 0.82f) ) ); System.out.printf("done.\n"); } } /** * @author ibarland * @version 2025-Jan-23 * * @license CC-BY -- share/adapt this file freely, but include attribution, thx. * https://creativecommons.org/licenses/by/4.0/ * https://creativecommons.org/licenses/by/4.0/legalcode * Including a link to the *original* file satisifies "appropriate attribution". */