├── README.md └── tricks.md /README.md: -------------------------------------------------------------------------------- 1 | # CS4-notes 2 | Notes for CS4 game course 3 | 4 | > Please consider contributing 5 | 6 | ## Final modifier 7 | 8 | If you don't want a method to be overridden. 9 | ``` java 10 | public final void doSomething(){ 11 | 12 | } 13 | ``` 14 | 15 | If you don't want a class to be inherited, you can use the final 16 | modifier too. 17 | 18 | ```java 19 | public final class Hello{ 20 | ... 21 | } 22 | ``` 23 | 24 | ## Refrence type vs Object type 25 | refrence type is the type written before equal and object type is the type we call constructor from it 26 | ```java 27 | public class A { 28 | char x = 'A'; 29 | public void run { 30 | System.out.println("Object type is A"); 31 | } 32 | } 33 | ``` 34 | ```java 35 | public class B extends A { 36 | char x = 'B' 37 | public void run { 38 | System.out.println("Object type is B"); 39 | } 40 | } 41 | ``` 42 | 43 | ##### what would be result of? 44 | 45 | ```java 46 | A a = new A (); 47 | B b = new B (); 48 | A trick = new B(); 49 | ``` 50 | 51 | ```java 52 | System.out.println(a.x); 53 | System.out.println(b.x); 54 | System.out.println(trick.x); 55 | 56 | System.out.println("------"); 57 | 58 | a.run(); 59 | b.run(); 60 | trick.run(); 61 | ``` 62 | Results are 63 | ``` 64 | A 65 | B 66 | A 67 | ------ 68 | Object type is A 69 | Object type is B 70 | Object type is B 71 | ``` 72 | `conclusion` late binding does not apply to instance variable but apply to instance methods 73 | 74 | `Please Note:` late binding can be applied to static variables. 75 | 76 | You can extend (only one class) and then implement (any number of interfaces). Respectively. *Java doesn't have multiple inheritance* 77 | 78 | 79 | #### For the following code : 80 | 81 | ```java 82 | 83 | public class A { 84 | char x = 'A'; 85 | public void run() { 86 | System.out.println("runA"); 87 | } 88 | public void run2() { 89 | System.out.println("run2A"); 90 | } 91 | } 92 | 93 | public class B extends A { 94 | char x = 'B'; 95 | 96 | public void run() { 97 | System.out.println("runB"); 98 | } 99 | 100 | public void run3() { 101 | System.out.println("run3B"); 102 | } 103 | } 104 | 105 | public static void main(String[] args) { 106 | A trick = new B(); 107 | 108 | // Code block inserted here 109 | } 110 | ``` 111 | #### What would be the result of : 112 | ``` 113 | trick.run(); 114 | ``` 115 | ``` 116 | trick.run2(); 117 | ``` 118 | ``` 119 | trick.run3(); 120 | ``` 121 | #### Results are : 122 | ``` 123 | runB 124 | ``` 125 | ``` 126 | run2A 127 | ``` 128 | ``` 129 | // compile error 130 | cannot find symbol 131 | symbol: method run3() 132 | location: variable trick of type Main.A 133 | ``` 134 | 135 | ## Type Casting 136 | ```java 137 | public class Animal { 138 | public void run (){ 139 | System.out.println ("can have 2 or 4 legs"); 140 | } 141 | } 142 | ``` 143 | ```java 144 | public class FourLegsAnimal extends Animal { 145 | public void run (){ 146 | System.out.println("actually has 4 legs"); 147 | } 148 | } 149 | ``` 150 | ```java 151 | public class Dog extends FourLegsAnimal{ 152 | public void run (){ 153 | System.out.println("It's a dog"); 154 | } 155 | } 156 | ``` 157 | what would be the output of 158 | ```java 159 | Animal d = new Dog (); 160 | d.run(); 161 | ((Animal) d).run(); 162 | ((FourLegsAnimal) d).run(); 163 | ``` 164 | Output is 165 | It's a dog 166 | 167 | It's a dog 168 | 169 | It's a dog 170 | 171 | `conclusion` type cast does not affect method calls (it will be called from object type class) 172 | 173 | What about 174 | ```java 175 | Animal a = new FourLegsAnimal(); 176 | ((Dog) a).run(); 177 | ``` 178 | it will give a run time error cannot cast from FourLegsAnimal to Dog 179 | `Note` you can not type cast to lower class (sub class) (`important` lower Class means lower class of object type). 180 | let's Add 181 | ```java 182 | public class TwoLegsAnimal extends Animal { 183 | public void run (){ 184 | System.out.println("actually has 2 legs"); 185 | } 186 | } 187 | ``` 188 | The OutputOf 189 | ```java 190 | FourLegsAnimal a1 = new FourLegsAnimal(); 191 | Animal a2 = new FourLegsAnimal(); 192 | ((TowLegsAnimal) a1).run(); 193 | ((TowLegsAnimal) a2).run(); 194 | ``` 195 | ``` 196 | Compile error 197 | RunTime Error 198 | ``` 199 | `impportant` you cannot type cast 2 classes in different branches , compile error depend on referenceType but runTimeErroe depends on ObjectType 200 | 201 | ## Multiple Inheritance 202 | You can extend (only one class) and then implement (any number of interfaces). Respectively. *Java doesn't have multiple inheritance* 203 | 204 | ## Cases of Type Casting 205 | 206 | ```java 207 | Person p = new Person(); 208 | Student s = new Student(); // Student extends Person 209 | Teacher t = new Teacher(); // Teacher extends Person 210 | 211 | Person ps = new Student(); 212 | Person pt = new Teacher(); 213 | 214 | Student sp = new Person(); // compilation error 215 | Student st = new Teacher(); // compilation error 216 | 217 | Teacher tp = new Person(); // compilation error 218 | Teacher ts = new Student(); // compilation error 219 | 220 | System.out.println((Student) p); // run time error 221 | System.out.println((Teacher) p); // run time error 222 | 223 | System.out.println((Person) s); 224 | System.out.println((Teacher) s); // compilation error 225 | 226 | System.out.println((Person) t); 227 | System.out.println((Student) t); // compilation error 228 | 229 | 230 | System.out.println((Person) ps); 231 | System.out.println((Student) ps); 232 | System.out.println((Teacher) ps); // run time error 233 | System.out.println((Person) pt); 234 | System.out.println((Student) pt); // run time error 235 | System.out.println((Teacher) pt); 236 | ``` 237 | 238 | 239 | 240 | ## Inheritance 241 | 242 | What is the **OUTPUT** of the following **CODE** 243 | 244 | ```java 245 | public class Parent{ 246 | public void c1(){ 247 | System.out.print("1"); 248 | c2(); 249 | } 250 | public void c2(){ 251 | System.out.print("2"); 252 | } 253 | } 254 | public class Child extends Parent{ 255 | public void c1(){ 256 | super.c1(); 257 | System.out.print("3"); 258 | } 259 | public void c2(){ 260 | super.c2(); 261 | System.out.print("4"); 262 | } 263 | public static void main(String [] args){ 264 | Parent p = new Child(); 265 | p.c1(); 266 | } 267 | } 268 | ``` 269 | **OUTPUT:** 1243 270 | 271 | In inheritance, you inherit all the public and private instance variables, but you can only access the public ones. 272 | 273 | Look at the following Example and give the output of the 4 print statements: 274 | 275 | ```java 276 | public class Person { 277 | static int counter = 0; // what if this was private? 278 | String name; 279 | int age; 280 | 281 | public Person(String name, int age) { 282 | this.name = name; 283 | this.age = age; 284 | counter++; 285 | } 286 | 287 | public static void main(String [] args) { 288 | Person p1 = new Person("Salah",19); 289 | Student1 s1 = new Student1("Sayed", 24); 290 | Student2 s2 = new Student2("Samir", 28); 291 | Student3 s3 = new Student3("Sameh", 31); 292 | System.out.println(Person.counter); 293 | System.out.println(Student1.counter); 294 | System.out.println(Student2.counter); 295 | System.out.println(Student3.counter); 296 | } 297 | } 298 | 299 | public class Student1 extends Person { 300 | public Student1(String name, int age) { 301 | super(name, age); 302 | } 303 | } 304 | 305 | public class Student2 extends Person { 306 | static int counter = 0; 307 | public Student2(String name, int age) { 308 | super(name, age); 309 | } 310 | } 311 | 312 | public class Student3 extends Person { 313 | static int counter=0; 314 | 315 | public Student3(String name, int age) { 316 | super(name, age); 317 | counter++; 318 | } 319 | } 320 | ``` 321 | 322 | ``` 323 | Result: 324 | 4 // Each created object (Person or any student) incremented the static counter variable in Person 325 | 4 // Student1 inherits the same static counter variable in Person 326 | 0 // Student2 overrides the static counter variable in Person and starts from 0, the increment in the super class is reflected only in the super class' static variable 327 | 1 // Student3 overrides the static counter variable in Person but increments its new overriden static counter 328 | 329 | ``` 330 | 331 | ## Exceptions 332 | 333 | The following code will not compile the NullPointerException catch block is unreachable because NullPointerException is a subClass of Exception 334 | 335 | ```java 336 | public void method(){ 337 | try{ 338 | //Something 339 | } catch (Exception e){ 340 | //Something 341 | } catch (NullPointerException e) { 342 | //Something 343 | } 344 | } 345 | ``` 346 | While the following code will compile and run since because the compiler can't see that the second catch block is unreachable 347 | 348 | ```java 349 | public void method(){ 350 | try{ 351 | //Something 352 | } catch (Exception e){ 353 | //Something 354 | } 355 | } 356 | public void methodCaller(){ 357 | try{ 358 | method() 359 | } catch (NullPointerException e){ 360 | //Something 361 | } 362 | } 363 | 364 | ``` 365 | Exceptions can only be thrown from methods or constructors. 366 | 367 | Class Cast Exceptions are thrown when you try to cast a parent into it's child. (thrown in run time) 368 | 369 | 370 | **Note:** Unchecked exceptions such as ArithmeticException , nullpointerException and RuntimeException needn't be declared in method signature. 371 | 372 | ## Abstraction 373 | 374 | The abstract methods in any abstract class must be defined once the subclass is not Abstract. Meaning that if an abstract class extends another abstract one you cannot have a body for the method in either class :) 375 | 376 | ## Interfaces 377 | 378 | 1. Any method written in an interface is set to be (public) by default. 379 | 2. You can never use the word **new** before an interface or an abstract class name, but you can the name of the interface itself to have objects of that type. See below 380 | 3. Interfaces can inherit from another interface 381 | 4. Abstract class can implement an interface without providing an implementation for methods 382 | 5. Interfaces can contain static methods with body 383 | ```java 384 | 385 | // Assume we have an interface/abstract class called Person, 386 | and a class Student that extends person. 387 | 388 | Person myPerson = new Person(); // This is wrong XXX. 389 | Person myPerson = new Student(); // This is okay. 390 | 391 | 392 | ``` 393 | 394 | 3. An interface can't have instance variables (by logic because we can't make instances of it) but it may have static variables. 395 | 396 | ## Encapsulation : 397 | 398 | 1. A private constructor = you cannot instantiate an object from that class. 399 | 2. You can't override public methods in the parent class with a private ones in the child class. 400 | 401 | Overriding (children) has to be less restrictive ! 402 | 403 | OR the parent has to be more strict ;) 404 | 405 | private -> default -> protected -> public. 406 | 407 | from high to low restriction. 408 | 409 | 3. You can't have a private class in a new .java file.
410 | but you can have it inside the class you're working on. See below . 411 | 412 | This is okay. 413 | ```java 414 | 415 | public class Person { // you can remove the public to use that class within the package only 416 | 417 | private class Salah{ 418 | 419 | } 420 | 421 | } 422 | 423 | ``` 424 | But this is wrong XXX: 425 | ```java 426 | 427 | private class Person { 428 | 429 | //Constructors and methods 430 | 431 | } 432 | 433 | 434 | ``` 435 | 436 | Note that you can use the default access modifier with the class in our case 1. 437 | 438 | ### Access Modifiers Summary: 439 | 1. public: Members available everywhere 440 | 2. private: Members available only in the class 441 | 3. default: Members available in the same class,package only. 442 | 4. protected: Members available in the same class,package and another package but a subclass of this class. 443 | **Note** : default is more protected than the protected access modifier :O 444 | 445 | 446 | ## Overriding vs Overloading 447 | Overriding is to override the logic of a function in the parent class. The overriding function must have the exact same signature (return type, parameters and name). 448 | However, overloading is the idea of adding methods with the same name but different signature. The old function can still be called normally. 449 | 450 | **Note:** you cannot write the same method signature (same name, and same parameters in same locations) twice with a different return type. 451 | 452 | ```java 453 | class A { 454 | protected void method() 455 | { 456 | System.out.println("AHello"); 457 | } 458 | 459 | 460 | public static class B extends A { 461 | 462 | public void method() 463 | { 464 | System.out.println("BHello"); 465 | } 466 | 467 | 468 | public static void main(String args[]) 469 | { 470 | A b = new B(); 471 | b.method(); 472 | } 473 | } 474 | ``` 475 | **Output:** BHello 476 | 477 | 478 | ```java 479 | class A { 480 | private void method() 481 | { 482 | System.out.println("AHello"); 483 | } 484 | 485 | 486 | public static class B extends A { 487 | 488 | public void method() 489 | { 490 | System.out.println("BHello"); 491 | } 492 | 493 | 494 | public static void main(String args[]) 495 | { 496 | A b = new B(); 497 | b.method(); 498 | } 499 | } 500 | 501 | ``` 502 | **Output:** AHello 503 | 504 | **Note**: At runtime it prints the output of the method from the **subclass** if the access modifier of the super class was **public,protected or default** , **if** it was **private** it prints the output of the method from the **super class** 505 | 506 | ## Throwing Exceptions in overriding methods 507 | 508 | An overriding method can throw any unchecked exceptions, regardless of whether the overridden method throws exceptions or not. However, the overriding method should not throw checked exceptions that are new or broader than the ones declared by the overridden method. The overriding method can throw narrower (Subclass of the thrown exceptions) or fewer exceptions than the overridden method. 509 | 510 | 511 | ```java 512 | import java.io.File; 513 | import java.io.FileNotFoundException; 514 | import java.io.IOException; 515 | import java.util.Scanner; 516 | abstract class Super { 517 | public String readFile(String path) throws IOException { 518 | throw new IOException(); 519 | } 520 | 521 | static class ExceptionsExample extends Super { 522 | @Override 523 | public String readFile(String path) throws FileNotFoundException { 524 | Scanner sc = new Scanner(new File("E://test//sample.txt")); 525 | String input; 526 | StringBuffer sb = new StringBuffer(); 527 | while (sc.hasNextLine()) { 528 | input = sc.nextLine(); 529 | sb.append(" "+input); 530 | } 531 | return sb.toString(); 532 | } 533 | 534 | } 535 | public static void main(String args[]) { 536 | String path = "E://test//sample.txt"; 537 | ExceptionsExample obj = new ExceptionsExample(); 538 | try { 539 | System.out.println(obj.readFile(path)); 540 | }catch(FileNotFoundException e) { 541 | System.out.println("Make sure the specified file exists"); 542 | } 543 | } 544 | 545 | } 546 | 547 | 548 | ``` 549 | **OUTPUT:** Make sure the specified file exists 550 | 551 | 552 | 553 | 554 | 555 | ```java 556 | 557 | import java.io.File; 558 | import java.io.FileNotFoundException; 559 | import java.io.IOException; 560 | import java.util.Scanner; 561 | abstract class Super { 562 | public String readFile(String path) throws IOException { 563 | throw new IOException(); 564 | } 565 | 566 | static class ExceptionsExample extends Super { 567 | @Override 568 | public String readFile(String path) throws Exception { //broader 569 | Scanner sc = new Scanner(new File("E://test//sample.txt")); 570 | String input; 571 | StringBuffer sb = new StringBuffer(); 572 | while (sc.hasNextLine()) { 573 | input = sc.nextLine(); 574 | sb.append(" "+input); 575 | } 576 | return sb.toString(); 577 | } 578 | 579 | } 580 | public static void main(String args[]) { 581 | String path = "E://test//sample.txt"; 582 | ExceptionsExample obj = new ExceptionsExample(); 583 | try { 584 | System.out.println(obj.readFile(path)); 585 | }catch(FileNotFoundException e) { 586 | System.out.println("Make sure the specified file exists"); 587 | } 588 | } 589 | 590 | } 591 | 592 | ``` 593 | **Compile error** 594 | 595 | 596 | 597 | -------------------------------------------------------------------------------- /tricks.md: -------------------------------------------------------------------------------- 1 | ## Refrence type vs Object type 2 | refrence type is the type written before equal and object type is the type we call constructor from it 3 | ```java 4 | public class A { 5 | char x = 'A'; 6 | public void run() { 7 | System.out.println("Object type is A"); 8 | } 9 | } 10 | public class B extends A { 11 | char x = 'B'; 12 | public void run() { 13 | System.out.println("Object type is B"); 14 | } 15 | } 16 | ``` 17 | 18 | ### (1) What would be result of 19 | 20 | ```java 21 | A a = new A (); 22 | B b = new B (); 23 | A trick = new B(); 24 | 25 | System.out.println(a.x); 26 | System.out.println(b.x); 27 | System.out.println(trick.x); 28 | 29 | a.run(); 30 | b.run(); 31 | trick.run(); 32 | ``` 33 | ``` 34 | A 35 | 36 | B 37 | 38 | A 39 | 40 | Object type is A 41 | 42 | Object type is B 43 | 44 | Object type is B 45 | ``` 46 | `conclusion` late binding does not apply to instance variable but apply to instance methods 47 | 48 | You can extend (only one class) and then implement (any number of interfaces). Respectively. *Java doesn't have multiple inheritance* 49 | 50 | ### (2) For the following code : 51 | 52 | ```java 53 | 54 | public class A { 55 | char x = 'A'; 56 | public void run() { 57 | System.out.println("runA"); 58 | } 59 | public void run2() { 60 | System.out.println("run2A"); 61 | } 62 | } 63 | 64 | public class B extends A { 65 | char x = 'B'; 66 | 67 | public void run() { 68 | System.out.println("runB"); 69 | } 70 | 71 | public void run3() { 72 | System.out.println("run3B"); 73 | } 74 | } 75 | 76 | public static void main(String[] args) { 77 | A trick = new B(); 78 | 79 | // Code block inserted here 80 | } 81 | ``` 82 | #### What would be the result of : 83 | ``` 84 | trick.run(); 85 | ``` 86 | ``` 87 | trick.run2(); 88 | ``` 89 | ``` 90 | trick.run3(); 91 | ``` 92 | #### Results are : 93 | ``` 94 | runA 95 | ``` 96 | ``` 97 | runB 98 | ``` 99 | ``` 100 | // compile error 101 | cannot find symbol 102 | symbol: method run3() 103 | location: variable trick of type Main.A 104 | ``` 105 | 106 | 107 | ### (3) For the following code: 108 | 109 | ```java 110 | 111 | public class A { 112 | public void priv() { 113 | System.out.println("A"); 114 | } 115 | public void printPriv(A a) { 116 | a.priv(); 117 | } 118 | } 119 | 120 | public class B extends A { 121 | public void priv() { 122 | System.out.println("B"); 123 | } 124 | public void printPriv(B b) { 125 | b.priv(); 126 | } 127 | 128 | public static void main(String args[]) { 129 | A a = new A(); 130 | B b = new B(); 131 | 132 | a.printPriv(b); 133 | } 134 | } 135 | ``` 136 | 137 | #### The result is: 138 | ``` 139 | B 140 | ``` 141 | #### but if we declare A with the priv method private instead of public: 142 | 143 | ```java 144 | public class A { 145 | private void priv() { 146 | System.out.println("A"); 147 | } 148 | public void printPriv(A a) { 149 | a.priv(); 150 | } 151 | } 152 | ``` 153 | 154 | #### The result is now: 155 | ``` 156 | A 157 | ``` --------------------------------------------------------------------------------