5. Constructor
class CoOrds
{
public int x, y;
// Default constructor:
public CoOrds()
{
x = 0;
y = 0;
}
// A constructor with two arguments:
public CoOrds(int x, int y)
{
this.x = x;
this.y = y;
}
// Override the ToString method:
public override string ToString()
{
return (String.Format("({0},{1})", x, y));
}
}
class MainClass
{
static void Main()
{
CoOrds p1 = new CoOrds();
CoOrds p2 = new CoOrds(5, 3);
// Display the results using the
// overriden ToString method:
Console.WriteLine("CoOrds #1 at {0}", p1);
Console.WriteLine("CoOrds #2 at {0}", p2);
Console.ReadKey();
}
}
/* Output:
CoOrds #1 at (0,0)
CoOrds #2 at (5,3)
*/
Instantiation
constructors
8. “Because inheritance exposes a subclass
to details of its parent's implementation,
it's often said that "inheritance breaks
encapsulation”
Gang of Four, Design Patterns (Chapter 1)
12. Diamond Problem in C++
int main(void) {
D d(10);
d.set(20);
cout << d.get() << endl;
return 0;
}
class A{
public:
A (int x) : m_x(x) {}
int m_x;
};
class B : public A {
public:
B (int x) : A(x) {}
void set(int x) {
this -> m_x = x;
}
};
class C : public A {
public:
C (int x) : A(x) {}
int get(void) {
return this -> m_x;
}
};
class D : public B,public C {
public:
D (int x) : B(x),C(x) {}
};
13. Diamond Problem in C++
int main(void) {
D d(10);
d.set(20);
cout << d.get() << endl;
return 0;
}
class A{
public:
A (int x) : m_x(x) {}
int m_x;
};
class B : public A {
public:
B (int x) : A(x) {}
void set(int x) {
this -> m_x = x;
}
};
class C : public A {
public:
C (int x) : A(x) {}
int get(void) {
return this -> m_x;
}
};
class D : public B,public C {
public:
D (int x) : B(x),C(x) {}
};
D
B
A
C
A
22. C# Example
class A
{
public virtual void Y()
{
// Used when C is referenced through A.
Console.WriteLine("A.Y");
}
}
class B : A
{
public override void Y()
{
// Used when B is referenced through A.
Console.WriteLine("B.Y");
}
}
class Program
{
public static void Main()
{
ShowString();
ShowString("Category");
}
static void ShowString()
{
ShowString("Popular");
}
static void ShowString(string value)
{
Console.WriteLine(value);
}
}
override overload
23. Polymorphism
• Polymorphism means that the sender of a stimulus does not need to
know the receiving instance’s class. The receiving instance can
belonging to an arbitrary class.
• If an instance sends a stimulus to another instance, but does not
have to be aware of which class the receiving instance belongs to,
we say that we have polymorphism.
Object-Oriented Software Engineering: A Use Case Driven Approach
24. Polymorphism
public class Shape
{
public int X { get; private set; }
public int Y { get; private set; }
public int Height { get; set; }
public int Width { get; set; }
// Virtual method
public virtual void Draw()
{
Console.WriteLine("Performing base class drawing tasks");
}
}
class Circle : Shape
{
public override void Draw()
{
// Code to draw a circle...
Console.WriteLine("Drawing a circle");
base.Draw();
}
}
class Rectangle : Shape
{
public override void Draw()
{
// Code to draw a rectangle...
Console.WriteLine("Drawing a rectangle");
base.Draw();
}
}
static void Main(string[] args)
{
System.Collections.Generic.List<Shape> shapes = new System.Collections.Generic.List<Shape>();
shapes.Add(new Rectangle());
shapes.Add(new Circle());
foreach (Shape s in shapes)
{
s.Draw();
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
25. package main
import "fmt"
type Human interface {
myStereotype() string
}
type Man struct {
}
func (m Man) myStereotype() string {
return "I'm going fishing."
}
type Woman struct {
}
func (m Woman) myStereotype() string {
return "I'm going shopping."
}
func main() {
m := new (Man)
w := new (Woman)
//an array of Humans - we don't know whether Man or Woman
hArr := [...]Human{m, w} //array of 2 Humans. One is the type Man, one is the type Woman.
for n, _ := range (hArr) {
//appears as human type, but behavior changes depending on actual instance
fmt.Println("I'm a human, and my stereotype is: ", hArr[n].myStereotype())
}
}
26. “ When I see a bird that walks like a duck and
swims like a duck and quacks like a duck, I
call that bird a duck.”
Indiana poet James Whitcomb Riley
27. Duck typing
• can work the same as polymorphism, but without inheritance
• Polymorphism (in the context of object-oriented programming) means a subclass can
override a method of the base class. This means a method of a class can do different
things in subclasses. For example: a class Animal can have a method talk() and the
subclasses Dog and Cat of Animal can let the method talk() make different sounds.
• Duck typing means code will simply accept any object that has a particular method.
Let's say we have the following code: animal.quack(). If the given object animal has
the method we want to call then we're good (no additional type requirements needed).
It does not matter whether animal is actually a Duck or a different animal which also
happens to quack. That's why it is called duck typing: if it looks like a duck (e.g., it has
a method called quack() then we can act as if that object is a duck).
What is the difference between polymorphism and duck typing?
28. • Interface:
• An Interface is a special type of class that only provides a
specification (not an implementation) for its abstract members.
• Abstract classes:
• The main purpose of an abstract class is to define a common
interface for its subclasses.
29. Interface
• An interface defines the signature operations of an entity, it also sets
the communication boundary between two entities, in this case two
pieces of software. It generally refers to an abstraction that an asset
provides of itself to the outside.
• The main idea of an interface is to separate functions from
implementations.
http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/interface.html
31. public interface ISoundBehaviour {
public void makeSound();
}
public class MeowSound implements ISoundBehaviour {
public void makeSound() {
System.out.println("Meow");
}
}
public class RoarSound implements ISoundBehaviour {
public void makeSound() {
System.out.println("Roar!");
}
}
public class Cat {
private ISoundBehaviour sound = new MeowSound();
public void makeSound() {
this.sound.makeSound();
}
public void setSoundBehaviour(ISoundBehaviour newsound) {
this.sound = newsound;
}
}
public class Main {
public static void main(String args[]) {
Cat c = new Cat();
// Delegation
c.makeSound(); // Output: Meow
// now to change the sound it makes
ISoundBehaviour newsound = new RoarSound();
c.setSoundBehaviour(newsound);
// Delegation
c.makeSound(); // Output: Roar!
}
}
composition
strategy pattern
32. SOLID
• Single Responsibility Principle (SRP): There should never be more than one reason for a class
to change.
• Open Closed Principle (OCP): Software entities like classes, modules and functions should be
open for extension but closed for modifications.
• Liskov Substitution Principle (LSP): Inheritance should ensure that any property proved about
supertype objects also holds for subtype objects.
• Interface Segregation Principle (ISP): Clients should not be forced to depend upon interfaces
that they don't use.
• Dependency Inversion Principle (DIP): High-level modules should not depend on low-level
modules. Both should depend on abstractions. Abstractions should not depend on details.
Details should depend on abstractions.
40. public class ObjA
{
private ObjB obj = new ObjB();
public void SomeAction()
{
obj.Work();
}
}
public class ObjB
{
public void Work()
{
Console.WriteLine("objB Work");
}
}
public class ObjA
{
private ObjC obj = new ObjC();
public void SomeAction()
{
obj.Action();
}
}
public class ObjC
{
public void Action()
{
Console.WriteLine("objC Work");
}
}
41. public class ObjA
{
private ObjB obj = new ObjB();
public void SomeAction()
{
obj.Work();
}
}
public class ObjB
{
public void Work()
{
Console.WriteLine("objB Work");
}
}
public class ObjA
{
private ObjC obj = new ObjC();
public void SomeAction()
{
obj.Action();
}
}
public class ObjC
{
public void Action()
{
Console.WriteLine("objC Work");
}
}
public interface IObj
{
void DoWork();
}
public class ObjA
{
private IObj obj = new ObjB();
public void SomeAction()
{
obj.DoWork();
}
}
public class ObjB : IObj
{
public void DoWork()
{
Console.WriteLine("objB Work");
}
}
public class ObjC : IObj
{
public void DoWork()
{
Console.WriteLine("objC Work");
}
}
42. public class ObjA
{
private IObj obj;
public void ObjA(IObj obj)
{
this.obj = obj;
}
public void SomeAction()
{
obj.DoWork();
}
}
public class ObjA
{
private IObj obj;
public IObj Obj
{
get
{
return this.obj;
}
set
{
this.obj = value;
}
}
public void SomeAction()
{
if (this.obj == null)
{
throw new ArgumentNullException("obj", "obj is null");
}
obj.DoWork();
}
}
public class ObjA
{
public void SomeAction(IObj obj)
{
if (obj == null)
{
throw new ArgumentNullException("obj", "obj is null");
}
obj.DoWork();
}
}
Inversion of Control (IoC)
(via Dependency Injection )
constructor injection
method injection
property injection
43. Law of Demeter (LoD)
• aka. Principle of Least Knowledge ( )
• Only talk to your immediate friends.
• Don't talk to strangers.
•
•
44. public class LawOfDemeterInJava
{
private Topping cheeseTopping;
/**
* Good examples of following the Law of Demeter.
*/
public void goodExamples(Pizza pizza)
{
Foo foo = new Foo();
// (1) it's okay to call our own methods
doSomething();
// (2) it's okay to call methods on objects passed in to our method
int price = pizza.getPrice();
// (3) it's okay to call methods on any objects we create
cheeseTopping = new CheeseTopping();
float weight = cheeseTopping.getWeightUsed();
// (4) any directly held component objects
foo.doBar();
}
private void doSomething()
{
// do something here ...
}
}
http://alvinalexander.com/java/java-law-of-demeter-java-examples
Facade Mediator
45. Design Patterns
• Favor Composition over inheritance
• Program to an interface, not an implementation
• High Cohesion & Low/Loose coupling
46. 1. Passes all tests
2. Expresses Intent (Self-document)
1. idea per method / class
2. Names of variables / methods / classes reveal intent
3. Methods & classes are understandable from their public
interface
3. No Duplicates (DRY)
4. Has no superfluous parts
1. Minimal methods / classes / modules
2. Only add what you need right now (YAGNI)
Xp Simplicity Rules - Kent Beck
47. Always implement things when you actually need
them, never when you just foresee that you need
them.
YAGNI (YouArentGonnaNeedIt)
48. “ The first time you do something, you just do it.
The second time you do something similar, you wince at
the duplication, but you do the duplicate thing anyway.
The third time you do something similar, you refactor.”
The Rule of Three - Don Roberts
3 Is A Magic Number
49. ♪ Sign, sign, everywhere a sign
Blockin' out the scenery, breakin' my mind
Do this, don't do that, can't you read the sign ♪
Five Man Electrical Band - Signs
50. Sometimes data is just data and functions are
just functions.
Rob Pike
• Understanding Object Oriented Programming
•
• Rob Pike's comment
51. References
• Object-Oriented Software Engineering: A Use Case Driven Approach
• Refactoring: Improving the Design of Existing Code
• Object Oriented Concepts and Principles
• Go
•
• Kent Beck
•