0% found this document useful (0 votes)
9 views52 pages

Lecture 5

The document discusses the concepts of interfaces, enums, mixins, and traits in object-oriented programming, particularly in Java. It explains the structure and inheritance of interfaces, the differences between interfaces and abstract classes, and the use of interfaces in software engineering, including dependency injection and factory patterns. Additionally, it covers method invocation expressions and the implications of interface evolution on software design.

Uploaded by

moh570kamil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views52 pages

Lecture 5

The document discusses the concepts of interfaces, enums, mixins, and traits in object-oriented programming, particularly in Java. It explains the structure and inheritance of interfaces, the differences between interfaces and abstract classes, and the use of interfaces in software engineering, including dependency injection and factory patterns. Additionally, it covers method invocation expressions and the implications of interface evolution on software design.

Uploaded by

moh570kamil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 52

CS 474: OOLE

Lecture 5: Interfaces,
Enums, Mixins, Traits
Instructor: Dr. Mark Grechanik
University of Illinois at Chicago
Interfaces

n An interface declaration introduces a new reference


type whose members are classes, interfaces,
constants, and methods (JLS Ch.9).
n This type has no instance variables, and typically
declares one or more abstract methods; otherwise
unrelated classes can implement the interface by
providing implementations for its abstract methods.
n Interfaces may not be directly instantiated.
n A nested interface is any interface whose
declaration occurs within the body of another class
or interface.
n A top level interface is an interface that is not a
nested interface.
Interface Inheritance/Implementation
n An interface may be declared to be a direct extension of
one or more other interfaces, meaning that it inherits all
the member types, instance methods, and constants of
the interfaces it extends, except for any members that it
may override or hide.
n A class may be declared to directly implement one or
more interfaces, meaning that any instance of the class
implements all the abstract methods specified by the
interface or interfaces.
q A class necessarily implements all the interfaces that its direct
superclasses and direct superinterfaces do.
q This (multiple) interface inheritance allows objects to support
(multiple) common behaviors without sharing a superclass.
Department of Computer Science, the
University of Illinois at Chicago 3
Variables of the Type <Interface>

n A variable whose declared type is an


interface type may have as its value a
reference to any instance of a class which
implements the specified interface.
n It is not sufficient that the class happen to
implement all the abstract methods of the
interface; the class or one of its superclasses
must actually be declared to implement the
interface, or else the class is not considered
to implement the interface.
Department of Computer Science, the
University of Illinois at Chicago 4
What Will Be Printed Out On the
Console?

public interface IReader {} public class MainClass {


public interface IWriter {} public static void main(String[] args) {
public interface IWorker Class worker = IWorker.class;
extends IReader {} while( worker != null ){
System.out.println(worker.getName());
worker = worker.getSuperclass();
}}}
What Will Be Printed Out On the
Console?

public interface IReader {} public class MainClass {


public interface IWriter {} public static void main(String[] args) {
public interface IWorker Class worker = IWorker.class;
extends IReader {} while( worker != null ){
System.out.println(worker.getName());
worker = worker.getSuperclass();
}}}

getSuperclass
public Class<? super T> getSuperclass()
Returns the Class representing the superclass of the entity (class, interface, primitive type or void) represented by
this Class. If this Class represents either the Object class, an interface, a primitive type, or void, then null is returned.
If this object represents an array class then the Class object representing the Object class is returned.
Returns:
the superclass of the class represented by this object.
What Will Be Printed Out On the
Console?

public interface IReader {} public class MainClass {


public interface IWriter {} public static void main(String[] args) {
public interface IWorker Class worker = IWorker.class;
extends IReader, while( worker != null ){
IWriter {} System.out.println(worker.getName());
worker = worker.getSuperclass();
}}}

getSuperclass
public Class<? super T> getSuperclass()
Returns the Class representing the superclass of the entity (class, interface, primitive type or void) represented by
this Class. If this Class represents either the Object class, an interface, a primitive type, or void, then null is returned.
If this object represents an array class then the Class object representing the Object class is returned.
Returns:
the superclass of the class represented by this object.
Super And Subinterfaces:
JLS, Ch. 9.1.3
n If an extends clause is provided, then the
interface being declared extends each of the
other named interfaces and therefore inherits
the member types, methods, and constants of
each of the other named interfaces.

n These other named interfaces are the direct


superinterfaces of the interface being declared.

n Any class that implements the declared interface


is also considered to implement all the interfaces
that this interface extends.
More on Super And Subinterfaces:
JLS, Ch. 9.1.3
n The superinterface relationship is the transitive closure of
the direct superinterface relationship. An interface K is a
superinterface of interface I if either of the following is true:
q K is a direct superinterface of I.
q There exists an interface J such that K is a superinterface of J,
and J is a superinterface of I, applying this definition recursively.
n Interface I is said to be a subinterface of interface K
whenever K is a superinterface of I.
n While every class is an extension of class Object, there is
no single interface of which all interfaces are extensions.
n An interface I directly depends on a type T if T is mentioned
in the extends clause of I either as a superinterface or as a
qualifier in the fully qualified form of a superinterface name.
Can We Write The Following Code?

public interface IReader extends IReader {}


public interface IWriter extends Ireader {}
public interface IReader extends IWriter {}

It is a compile-time error if an interface depends on itself.

If circularly declared interfaces are detected at run time, as


interfaces are loaded, then a ClassCircularityError is thrown
(§12.2.1).
Some Differences Between Interfaces
And Abstract Classes in Java
n An abstract class may contain fields, which are not static and
final as is the case with interfaces.
n It may have few (or all) implemented methods as well, whereas
Interfaces can’t have any implementation code. All the methods
of an interface are by default abstract. Methods/Members of an
abstract class may have any visibility: public, protected, private,
none (package). But, those of an interface can have only one
type of visibility: public.
n An abstract class automatically inherits the Object class and
thereby includes methods like clone(), equals(), etc. There is no
such thing with an interface. Likewise, an abstract class can have
a constructor, unlike an interface.
n Interfaces are used to implement multiple inheritance in Java as
a class in Java can explicitly have only one super class, but it
can implement any number of interfaces.
Default And Static Methods of
Interfaces in JLS: Static Methods Are
Not Inherited!
public interface IReader { public class MainClass {
default String read(){ public static void main(String[] args) {
return "Hello"; Class worker = IWorker.class;
}} while( worker != null ){
public interface IWriter { System.out.println(worker.getName());
static String ready(){ worker = worker.getSuperclass();
return "Ready"; worker.read();
}} IWriter.ready();
public interface IWorker }}}
extends IReader,
IWriter {}
Interface Library Evolution
Library-Reader-v1.0.jar Program Uses Library-Reader
public interface IReader {
public void init() import Library-Reader.*
public String read()
} public class MainClass
implements IReader {
@Override public void init() {
System.out.println(“init”);
Library-Reader-v2.0.jar }
public interface IReader { @Override public String read() {
public void init() return(“read”);
// public String read()
} }
public static void main(
String[] args) {
new MainClass().init()
new MainClass().read()
}
Answer: JLS, Ch. 13 }
Interface Library Evolution
Library-Reader-v1.0.jar Program Uses Library-Reader
public interface IReader {
public void init() import Library-Reader.*
public String read() public class MainClass implements IReader {
} public void init() {
System.out.println(“init”);
}
public String read() {
return(“read”);
}
public static void main(String[] args) {
new MainClass().init()
Library-Reader-v2.0.jar }
new MainClass().read()

}
public interface IReader {
public void init()
// public String read()
}

Answer: JLS, Ch. 13.4.24


Interface Library Evolution
Library-Reader-v1.0.jar Program Uses Library-Reader
public interface IReader { import Library-Reader.*
public void init()
public String read() public class MainClass implements IReader
} {
public void init() {
System.out.println(“init”);
}
public String read() {
return(“read”);
}
public static void main(String[] args) {
Library-Reader-v2.0.jar IReader reader = new MainClass()
reader.init()
public interface IReader { reader.read()
public void init() }
// public String read()
}
}
Interface Library Evolution
Library-Reader-v1.0.jar
public interface IReader {
public void init()
Program Uses Library-Reader
public String read()
} import Library-Reader.*
public class MainClass implements IReader {
public void init() {
System.out.println(“init”);
}
public String read() {
return(“read”);
}
public static void main(String[] args) {
IReader reader = new MainClass()
Library-Reader-v2.0.jar reader.init()
reader.read()
public interface IReader { }
public void init() }
// public String read()
}

Answer: JLS, Ch. 13.4.12 – linkage error, why?


Changing a Superclass
class Hyper {
void hello() { System.out.println("hello from Hyper"); }
}
class Super extends Hyper { }
class Test extends Super {
public static void main(String[] args) {
new Test().hello();
}
void hello() {
super.hello();
}
}

Department of Computer Science, the


University of Illinois at Chicago 17
Changing a Superclass
class Hyper {
void hello() { System.out.println("hello from Hyper"); }
}
class Super extends Hyper { }
class Test extends Super {
public static void main(String[] args) {
new Test().hello();
}
void hello() {
super.hello();
}
}

class Super extends Hyper {


void hello() { System.out.println("hello from Super"); }
}

Department of Computer Science, the


University of Illinois at Chicago 18
Using Interfaces In Software
Engineering
n The interface is a contract between the programmer and
the clients of the servers that implement this interface.
n The programmer can change the internal implementation
of the methods of the interface without affecting its
clients.
n An interface is a type. Parameters can be passed and
methods can return values declared as interface types,
requiring that way that parameters and return types
implement particular methods without necessarily
providing a concrete implementation for them.
n Enables straightforward implementation of dependency
injection, factory and many other patterns.
Factory Pattern Example
public abstract class
public interface IProduct { ProductAbstractFactory {
string GetName(); protected abstract IProduct
string SetPrice(double price); } DoSomething();
public class Phone : IProduct { public IProduct GetObject() {
private double _price; return this.DoSomething();}
}
public string GetName() {
return "Apple TouchPad"; } public class PhoneConcreteFactory :
ProductAbstractFactory {
public string SetPrice( protected override IProduct
double price) {
this._price = price; DoSomething()
return "success"; } {
} IProduct product = new Phone();
product.SetPrice(20.30);
return product; }
}

https://en.wikipedia.org/wiki/Factory_method_pattern
Dependency Injection With Interfaces
public interface IDependentClass { void DoSomethingInDependentClass(); }
public interface IInjectDependent { void InjectDependent(IDependentClass dependentClass); }

public class MainClass : IInjectDependent {


IDependentClass dependentClass;
public void DoSomething() { dependentClass.DoSomethingInDependentClass(); }
public void InjectDependent(IDependentClass dependentClass) {
this.dependentClass = dependentClass; }
}

public class DependentClass1 : IDependentClass {


public void DoSomethingInDependentClass()
Console.WriteLine("DependentClass1: I can be injected into MainClass");}
}

public class DependentClass2 : IDependentClass {


public void DoSomethingInDependentClass() {
Console.WriteLine("DependentClass2: I can be injected as well");
}
}

IDependentClass dependency = (IDependentClass)Activator.CreateInstance("DependentClass1");


MainClass mainClass = new MainClass();
((IInjectDependent)mainClass).InjectDependent(dependency);
mainClass.DoSomething();
Dependency Injection
n A dependency is an object that is passed to a client and
that can be used as a service.
n An injection a mechanism for passing a dependency to a
dependent object (i.e., a client) that would use this
passed object as a service.
n The client delegates the responsibility of providing its
dependencies to external code (i.e., the injector) without
calling the injector’s code.
n Dependency injection separates the creation of a client's
dependencies from the client's behavior, which allows
program designs to be loosely coupled and to follow the
dependency inversion and single responsibility principles
https://en.wikipedia.org/wiki/Dependency_injection
Interfaces And Reuse

n Interface implementation inheritance makes an


application more susceptible to dependency problems
because of the tight coupling between a sub class and
its super class.
n Changes to the superclass's interface can ripple out and
break any code that uses the superclass or any of its
subclasses.
n A change in the superinterface can break the code that
defines any of its subinterfaces.
n What if only some methods of the interface are needed?
n How can we avoid bloated designs?
Java super and this
n The form super.Identifier refers to the field named Identifier of the
current object, but with the current object viewed as an instance of
the superclass of the current class. JLS 15.11.2.
n The form T.super.Identifier refers to the field named Identifier of the
lexically enclosing instance corresponding to T, but with that
instance viewed as an instance of the superclass of T.
n The forms using the keyword super are valid only in an instance
method, instance initializer, or constructor of a class, or in the
initializer of an instance variable of a class. If they appear anywhere
else, a compile-time error occurs. Check it – it is your homework.
n When used as a primary expression, the keyword this denotes a
value that is a reference to the object for which the instance method
or default method was invoked, or to the object being constructed.
n The type of this is the class or interface type T within which the
keyword this occurs.
Department of Computer Science, the
University of Illinois at Chicago 24
Method Invocation Expressions When
Using Interfaces - JLS 15.12
class Superclass {
void foo() { System.out.println("Hi"); }
}

class Subclass1 extends Superclass {


void foo() { throw new UnsupportedOperationException(); }

Runnable tweak = new Runnable() {


void run() {
Subclass1.super.foo(); // Gets the 'println' behavior
}
};
}

Department of Computer Science, the


University of Illinois at Chicago 25
Method Invocation Expressions When
Using Interfaces - JLS 15.12 class Superclass {
void foo() { System.out.println("Hi"); }
}

class Subclass1 extends Superclass {


void foo() { throw new UnsupportedOperationException(); }

Runnable tweak = new Runnable() {


void run() {
Subclass1.super.foo(); // Gets the 'println' behavior
interface Superinterface { };
}

default void foo() { System.out.println("Hi"); } }

class Subclass2 implements Superinterface {


void foo() { throw new UnsupportedOperationException(); }

void tweak() {
Superinterface.super.foo(); // Gets the 'println' behavior
}
}
Department of Computer Science, the
University of Illinois at Chicago 26
Method Invocation Expressions When
Using Interfaces - JLS 15.12
class Subclass3 implements Superinterface {
void foo() { throw new
UnsupportedOperationException(); }

Runnable tweak = new Runnable() {


void run() {
Subclass3.Superinterface.super.foo(); }
};
}
Department of Computer Science, the
University of Illinois at Chicago 27
Method Invocation Expressions When
Using Interfaces - JLS 15.12
class Subclass3 implements Superinterface {
void foo() { throw new
UnsupportedOperationException(); }

Runnable tweak = new Runnable() {


void run() {
Subclass3.Superinterface.super.foo(); }
};
}
Department of Computer Science, the
University of Illinois at Chicago 28
Mixins
n Mix-in programming is a style of software development
where units of functionality are created in a class and
then mixed in with other classes, i.e., a programmer can
inject some code into a class.
n A mixin class acts as the parent class, containing the
desired functionality. A subclass can then inherit or
simply reuse this functionality, but not as a means of
specialization.
n The important difference between the concepts of mixins
and inheritance is that the child class can still inherit all
the features of the parent class, but, the semantics about
the child "being a kind of" the parent does not always
hold.
https://en.wikipedia.org/wiki/Mixin
Understanding Mixins Using Examples

public class Ship {


List<Cargo> cargoes;
public void addCargo(Cargo c){
cargoes.add(c);
}
public void removeCargo(Cargo c){
cargoes.remove(c);
}
}
public class Airport {
List<Aircraft> aircrafts;
public void land(Aircraft a) {
aircrafts.add(a);
}
public void depart(Aircraft a) {
aircrafts.remove(a);
}
}
Understanding Mixins Using Examples
public class Ship {
List<Cargo> cargoes;
public void addCargo(Cargo c){
cargoes.add(c);
} class AircraftCarrier extends
public void removeCargo(Cargo c){ Airport, Ship
cargoes.remove(c);
}
}
public class Airport {
List<Aircraft> aircrafts;
public void land(Aircraft a) {
aircrafts.add(a);
}
public void depart(Aircraft a) {
aircrafts.remove(a);
}
}
Understanding Mixins Using Examples
public class Ship {
List<Cargo> cargoes;
public void addCargo(Cargo c){
cargoes.add(c);
} class AircraftCarrier extends
public void removeCargo(Cargo c){ Airport, Ship
cargoes.remove(c);
}
}
public class Airport {
List<Aircraft> aircrafts;
public void land(Aircraft a) {
aircrafts.add(a);
}
public void depart(Aircraft a) {
aircrafts.remove(a);
}
}
Understanding Mixins Using Examples
public class Ship {
List<Cargo> cargoes;
public void addCargo(Cargo c){
cargoes.add(c);
}
public void removeCargo(Cargo c){ public interface Ship {
cargoes.remove(c); void addCargo(Cargo c);
} void removeCargo(Cargo c);
} }
public class Airport {
List<Aircraft> aircrafts; public interface Airport {
public void land(Aircraft a) { void land(Aircraft a);
aircrafts.add(a); void depart(Aircraft a);
} }
public void depart(Aircraft a) {
aircrafts.remove(a);
}
}
Understanding Mixins Using Examples

class AircraftCarrier implements Ship,


public interface Ship { Airport {
void addCargo(Cargo c); List<Aircraft> aircrafts;
List<Cargo> cargoes;
void removeCargo(Cargo c);
} public void land(Aircraft a) {
aircrafts.add(a);
public interface Airport { }
void land(Aircraft a); public void depart(Aircraft a) {
aircrafts.remove(a);
void depart(Aircraft a);
} }
public void addCargo(Cargo c){
cargoes.add(c);
}
public void removeCargo(Cargo c){
cargoes.remove(c);
}
}
Mixins in Java
public interface Airport {

List<Aircraft> getAircrafts();

default void land(Aircraft aircraft) { getAircrafts().add(aircraft); }

default void depart(Aircraft aircraft) { getAircrafts.remove(aircraft); }


}

class AircraftCarrier implements Ship, Airport {


List<Aircraft> aircrafts = new ArrayList<>();
List<Cargo> cargoes = new ArrayList<>();

@Override
public List<Aircraft> getAircrafts(){ return aircrafts; }

@Override
public List<Cargo> getCargoes(){ return cargoes; }
}
How Can It Be Done in Ruby Using
Mixins?
module Airport

@aircrafts = Array.new

def land(aircraft)
aircrafts.push(aircraft)
end

def depart(aircraft)
aircraft.delete(aircraft)
end
end

class AircraftCarrier
include Ship
include Airport
end
How Can It Be Done in Kotlin Using
Mixins?
interface Ship {
val cargoes : List<Cargo>

fun addCargo(c : Cargo){


cargoes.add(c)
}

fun removeCargo(c : Cargo) {


cargoes.remove(c)
}
}

class AircraftCarrier : Ship, Airport {


override val cargoes = ArrayList()
override val aircrafts = ArrayList()
}
How Can Mixins Be Implemented in
Scala Using Traits?
trait Airport {
trait Ship { val aircrafts :
val cargoes : ListBuffer[Cargo] ListBuffer[Aircrafts]

def addCargo(c : Cargo){ def land(a : Aircraft){


cargoes += c aircrafts += a
} }

def removeCargo(c : Cargo){ def depart(a : Aircraft){


cargoes -= c aircrafts -= a
} }
} }

class AircraftCarrier with Ship with Airport


Traits – Starting with advice from
Odersky
n If the behavior will not be reused, then make it a concrete
class.
n If you want to inherit from it in Java code, use an abstract
class.
n If you plan to distribute it in compiled form, and you expect
outside groups to write classes inheriting from it, you might
lean towards using an abstract class.
n If it might be reused in multiple, unrelated classes, make it
a trait. Only traits can be mixed into different parts of the
class hierarchy.
n If you still do not know, after considering the above, then
start by making it as a trait.
n What is a trait?!
Classes and Traits

n Classes retain their primary role as generators of


instances, while traits are purely units of reuse.

n Classes are organized in a single inheritance hierarchy,


thus avoiding the key problems of multiple inheritance,
but the incremental extensions that classes introduce to
their superclasses are specified using one or more traits.

n A trait is essentially a set of methods, i.e., a mapping


from method names to method bodies. Composite traits
may be specified by means of compositions.
Traits and Mixins
n Traits bear a superficial resemblance to mixins, with
several important differences.
n Several traits can be applied to a class in a single
operation, whereas mixins must be applied incrementally.
n Trait composition is unordered, thus avoiding problems due
to linearization of mixins.
n Traits contain only methods, so state conflicts are avoided,
but method conflicts may exist.
n A class is specified by composing a superclass with a set of
traits and some glue methods. Glue methods are defined in
the class and they connect the traits together; i.e., they
implement required trait methods (possibly by accessing
state), they adapt provided trait methods, and they resolve
method conflicts.
Traits As Stackable Modifications
n Traits let you modify the methods of a class, and they do so
in a way that allows you to stack those modifications with
each other.

n Consider stacking modifications to a queue of integers.


n The queue will have two operations: put, which places
integers in the queue, and get, which takes them back out.
Queues are first-in, first-out, so get should return the
integers in the same order they were put in the queue.
n Given a class that implements such a queue, you could
define traits to perform modifications such as these:
q Doubling: double all integers that are put in the queue
q Incrementing: increment all integers that are put in the queue
q Filtering: filter out negative integers from a queue
Basic Queue For Integers (FIFO)

abstract class IntQueue {


def get(): Int
def put(x: Int)
}

import scala.collection.mutable.ArrayBuffer
class BasicIntQueue extends IntQueue
{
private val buf = new ArrayBuffer[Int]

def get() = buf.remove(0)


def put(x: Int) = { buf += x }
}
Add Doubling Functionality
Mix it into a class that
extends IntQueue

trait Doubling extends IntQueue {


abstract override def put(x: Int) = { super.put(2 * x) } }

This is an abstract method!


Mixin should be ordered!

JSL Ch.15.12.1: Let T be the type declaration immediately enclosing the


method invocation. It is a compile-time error if I (the interface searched) is not
a direct superinterface of T, or if there exists some other direct superclass or
direct superinterface of T, J, such that J is a subtype of I.
Adding More Traits

trait Incrementing extends IntQueue {


abstract override def put(x: Int) = {
super.put(x + 1) }
}

trait Filtering extends IntQueue {


abstract override def put(x: Int) = {
if (x >= 0) super.put(x) } }
Using the Trait And Adding More
Traits
n class MyQueue extends BasicIntQueue with Doubling
n val queue = new BasicIntQueue with Doubling
n val queue1 = new BasicIntQueue with Incrementing with Filtering
n queue1.put(-1); queue.put(0); queue.put(1); queue.get() => 1
n Traits further to the right take effect first
n If that method calls super, it invokes the method in the next trait
to its left, and so on.
n In the example, Filtering's put is invoked first, so it removes
integers that were negative to begin with. Incrementing's put is
invoked second, so it adds one to those integers that remain.
n Why not multiple inheritance? It is your homework – read
Ordersky’s book on Scala.
Declaration enum

n An enum declaration specifies a new enum type, a


special kind of class type.
q {ClassModifier} enum TypeIdentifier [Superinterfaces] EnumBody
n It is a compile-time error if an enum declaration has the
modifier abstract or final.
n An enum type has no instances other than those defined
by its enum constants. It is a compile-time error to
attempt to explicitly instantiate an enum type.
n In addition to enum constants, the body of an enum
declaration may contain constructor and member
declarations as well as instance and static initializers.
Department of Computer Science, the
University of Illinois at Chicago 47
The Body of enum

n EnumBody: { [EnumConstantList] [,]


[EnumBodyDeclarations] }
n EnumConstantList: EnumConstant {,
EnumConstant}
n EnumConstant: {Annotation} Identifier
[( [ArgumentList] )] [ClassBody]
n ArgumentList:Expression {, Expression}
n EnumBodyDeclarations: ;
{ClassBodyDeclaration}
Department of Computer Science, the
University of Illinois at Chicago 48
enum Constants and Their
Anonymous Classes
n The optional class body of an enum constant implicitly
defines an anonymous class declaration that extends the
immediately enclosing enum type.
n The class body is governed by the usual rules of
anonymous classes; in particular it cannot contain any
constructors.
n Instance methods declared in these class bodies may be
invoked outside the enclosing enum type only if they
override accessible methods in the enclosing enum type
n An enum constant is said to be created when the
corresponding implicitly declared field is initialized.
Department of Computer Science, the
University of Illinois at Chicago 49
Use JLS to Create Samples With enum
public enum EnumStuff{
OPEN {
@Override
public boolean isDoorOpen() {
return true;
} public static void main(String...args){
}, EnumStuff s = OPEN;
CLOSED { System.out.println(s.isDoorOpen());
@Override }
public boolean isDoorOpen() { }
return true;
}
}, OPENING {
@Override
public boolean isDoorOpen() {
return false;
}
};
public abstract boolean isDoorOpen();
Department of Computer Science, the
University of Illinois at Chicago 50
Conclusions
n Code block modifiers enable programmers to
model complex systems to create program
entities with desired properties.
n Using inheritance, subtyping via interfaces,
and mixing enable programmers to write
concise code to implement complex
behavioral patterns.
n Enums are somewhat controversial, but their
use allow programmers to implement
effective typed iteration abstractions.
Department of Computer Science, the
University of Illinois at Chicago 51
Reading

n Mandatory
q Chapters 10-13 of the Scala book.
q JLS chapters 8.9; 9.1-9.5, 13

n Optional for undergrad, mandatory for grads:


q Schärli, Nathanael; Ducasse, Stéphane; Nierstrasz,
Oscar; Black, Andrew P. (2003). "Traits: Composable
Units of Behaviour" (PDF). Proceedings of the
European Conference on Object-Oriented
Programming (ECOOP). Lecture Notes in Computer
Science. Springer-Verlag. 2743: 248–274
Department of Computer Science, the
University of Illinois at Chicago 52

You might also like