An * abstract method* is a method with no code.

An * abstract class* ` A` is a class with at least one
abstract method `M`

The abstract class can contain a concrete method `G` that calls
`M`.

You cannot construct an object of type `A`. What you can
do is define a concrete subclass `S` of `A` that overrides
`A`'s definition of `M` with a concrete method.

Then construct an object `O` of class ` S` and call
`O.G(...)`. When `G` needs to call `M`, it will find
the `M` that belongs to `Q` (dynamic dispatching!), which
is the `M` defined for `S`.

Data field:

Abstract methods:

Concrete class ` Rect` extends ` Figure `.

Inherits field `boundingBox`.

Provides instantiation for `area, inside.`

Concrete class ` Circle ` extend ` Figure`

Inherits field `boundingBox`.

Provides instantiation for `area, inside.`

Question. Suppose that we define `Figure` as a concrete class,
and define `area` and ` inside` in some arbitrary way as
concrete methods

(e.g. `area` always returns 1.0 and
`inside` always returns ` true`.)

How would that affect what this code does?

What is the point of having abstract methods?

- Apply function
`F`to each object in array`A`and put the results in array`B` - To approximate the integral of
`F`from`A`to`B`. by the trapezoid rule with`N`

The obvious thing would be to write functions of the form
`ApplyToArray(A,B,F)` or `Trapezoid(F,A,B,N)`, which take
` F` as a parameter. There are programming languages that allow
this, with lesser and greater degrees of generality. However, Java is
not one of them.

If all the functions you are considering have the same type signature,
then Java provides two techniques for doing this: * abstract
methods* and *interfaces.* If you consider functions that
take and return different possible types, then you have to add on
* generics.*

**Abstract class:** `ArrayApplier`

**Abstract method:** `f`

**Concrete method:** of `ApplyToArray` is `ApplyToArray(A,B)`

**Concrete class** ` applyIncr ` extends `ArrayApplier`, and
overrides `f` with an increment function.

**Concrete class** ` applyDouble ` extends `ArrayApplier`, and
overrides `f` with a doubling function.

The ` main` method creates an object `Incr ` of class
` applyIncr` and calls `Incr.ApplyToArray(A,B)`.

When this calls `f` it calls `Incr`'s version of `f`
which is the one defined in `applyIncr`.

Note that these classes have no data fields, only methods. So you never need more than one object of these classes, which makes them a little strange.

**Abstract class:** `Trapezoid`

**Abstract method:** `f,` the function to be integrated.

**Concrete method:** `ComputeTrapezoid`, which implements the general
trapezoid algorithm, calling `f`

** Concrete class:** `TrapezoidSquare` extends ` Trapezoid,`
overriding
` f` as f(x) = x^2.

** Concrete class:** `TrapezoidW` extends
`Trapezoid`, overriding
`f` as f(x) = 1/(1+x^2).

An interface `I` is a collection of abstract methods e.g. `f`

Class `C` implements `I`, instantiates `f` as
a concrete method.

Method `M` has a formal parameter `X`of type `I.`.

Some function calls `M(Y)` where `Y` is of type `C`.

When `M` calls `X.f()`, this uses the definition of `Q`
in `C`

A class can implement many different interfaces.

** Interface:** `IntFun` with abstract method `f`.

`Incr` implements `IntFun` and instantiates`f` with the
increment function.

`Doub` implements `IntFun` and instantiates`f` with the
doubling function.

`ApplyToArray` takes an argument `Q` of type `IntFun`.

`main` creates object `Inc` of type `Incr`.
`main` calls `ApplyToArray(Inc,A,B).`

When `ApplyToArray`
calls `Q.f(A[i])`, since `Q` is bound to `Inc,` the
version of `f` defined in `Incr` is used.

Same thing for `Dub`

** Interface:** `Integrand` with abstract method `f`.

`XSquared` implements `IntFun` and instantiates`f` with the
function f(x)=x^2.

`WW` implements `Integrand` and instantiates`f` with the
function f(x)=1/(1+x^2).

`ComputeTrapezoid` takes an argument `Q` of type
`Integrand`.

`main` creates object `XS` of type `XSquared`.
`main` calls `ComputeTrapezoid(XS,A,B).`

When `ComputeTrapezoid`
calls `Q.f(...)`, since `Q` is bound to `XS,` the
version of `f` defined in `XSquared` is used.

Same thing for `WW`.