Classes and Interfaces Flashcards

1
Q

Describe why classes and methods should be inaccessible as possible and how to do this

A
  • One of the major tenets of software engineering is information hiding. We want modules to talk through exposed api and hide all implementation details. This allows us to understand modules separately from each other and maintain one part without worrying about the rest.
  • We do this by making classes and fields as inaccessible as possible.
  • At the level of class, only make classes that should be part of module api public and make the rest non-public so that they are only used within the module.
  • At the level of fields, classes that are part of module api should never have public fields. It may have protected field if it’s part of module api, but usually hot. It can have default visibility sometimes, but private is almost always preferable.
  • If the class is nonpublic, have public field maybe acceptable since changes will affect only that module and not clients
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Describe why mutability should be minimized and how this can be done.

A
  • The smaller the number of fields that are mutable in a class, the easier it is to reason about correctness of the class. So in general, we should strive towards immutable class whenever possible and smallest number of mutable fields if that’s not possible.
  • Immutable classes have a few advantages.
    1) Easy to reason about
    2) Is thread-safe. Once it’s created, its value can never be changed by any thread.
    3) Is a good building block for more complex class. For example, it can safely be used as key for hashmap.
  • Immutable class may lead to performance concern if client often do a multistep calculation, each of which require new object to be created. We can improve performance by
    1) Construct values commonly used in static fields and provide static factory method that return these.
    2) Cache instances that are commonly asked for in static factory method.
    3) Provide companion class like StringBuilder for doing multistep calculation.
  • To ensure class is immutable, you should do the following
    1) Make all fields that are exposed to user private final
    2) Make the class final
    3) Do not provide methods that modify state of variables.
    4) Make defensive copy of mutable objects passed into constructor. Make defensive copy of mutable objects given to client
    5) Make constructor private and provide static factory method to allow caching instances, etc.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Explain why composition should be preferred over inheritance.

A
  • Let’s say you have code in a class that you’d like to reuse, adding some extra functionalities to it. What’s the best way to do this?
  • Traditionally, this is done by inheriting the class and overriding some methods. There are a lot of problems with this approach, however - This breaks encapsulation because inheritance means you must know how superclass is implemented for you to be able to correctly subclass it.
  • For example, you may override a method addAll in a hashmap to keep track of number of values added, but the superclass may call into add to do the addition, and your tracking number would have been duplicated. This is an implementation detail that you have to be of because of inheritance.
  • Alternatively, you may try to enforce some invariance by overriding some methods, but the next release may add new methods to the class that you haven’t override yet, which means invariance can be broken!
  • Only use inheritance if
    1) The class is specially designed and documented for it
    2) The extended class really has is-a relationship with superclass
    3) Best if extended class is in the same package as superclass.
  • A much better way to do this is by composition - create a forwarding class that implements an interface then have your class extends this forwarding class, accepting the interface type. This allows you to wrap the old class and add additional functionalities safely.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Describe how to design and document for inheritance or alternatively, how to prevent it.

A
  • If you want to design a class to be inherited, every method that call overridable method must document this usage in the javadoc. That way, developers are aware that overriding these methods will affect the methods that call into these.
  • It is often necessary to provide some hook protected methods that can be overriden to improve performance or add functionalities as well. Best way to discover this is to add a few implementations yourself.
  • Note that the super constructor should not call any overridable methods. The super constructor gets called before child constructor, so if the overridable method is overridden and depends on state set up by child constructor, it would fail.
  • It’s clear than inheritance place a lot of limitations on implementation, so avoid it as much as possible.
  • You can enforce non-inheritance by making the class final or alternatively make all constructors private and provide static factory methods.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Explain why interfaces are preferable to abstract classes.

A
  • Abstract class is much more rigid than interfaces as a type because classes can extend only one class but can implement multiple interfaces.
  • ## You can create interfaces and use them as a mixin. You declare that the class is capable of doing something. You can’t do this with abstract class.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Explain how to use function objects to represent strategies.

A
  • Many languages allow you to pass function pointers and lambda expression into another function to modify its behavior.
  • This is not possible in java but you can simulate this using function objects.
  • Function objects are stateless objects, accepting some parameters and only operating on those parameters before returning.
  • Because they are stateless, it is best to create only one instance of these function objects and reuse them.
  • To allow clients to pass multiple strategies, an interface should also be declared, with each strategy implementing the interface.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Explain the difference between static and nonstatic classes.

A
  • Static classes should always be preferred over nonstatic classes. You can think of static class just like top-level class, just declared inside another class. It has access to all the private variable of the containing class.
  • Nonstatic classes contains reference to an instance of the container class and is useful if the class represents an alternative view of the containing class. An example of this is keyset and entryset of map.
  • Because nonstatic classes contain reference to containing class, the prevents containing class from being garbage collected, so make sure to use it only when it makes sense to do so.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly