Is it great to make classes as functions and declare parameter types using function types?

I'm working on a scala project and a colleague of mine who prefers a functional style and suggests a way to organize your code: defining classes as functions

Here's an example:

class FetchFeed extends (String => List[Feed]) {
   def apply(url:String):List[Feed] = ???
}

      

If another class needs this class, it will be declared using the type String => List[Feed]

class MyWork(fetchFeed: String => List[Feed])

      

Then at some point pass it FetchFeed

:

val fetchFeed = new FetchFeed
val myWork = new MyWork(fetchFeed)

      

The pros are that we can easily mock FetchFeed

by passing a function:

val myWork = new MyWork(_ => List(new Feed))

      

The syntax is simple and easy to read.

But the cons are that when I see the ad MyWork

:

class MyWork(fetchFeed: String => List[Feed])

      

It's hard to figure out which class will be passed, not even the IDE can help me. We need to search extends (String => List[Feed])

the code base or find a place to initialize new MyWork

.

And if there is another class that extends String => List[Feed]

but is never used in MyWork

, it often confuses me.

But if we declare it with a real type:

class MyWork(fetchFeed: FetchFeed)

      

It's easier to jump straight to the ads. But in this case, we cannot pass functions directly, instead we need:

val fetchFeed = mock[FetchFeed]
fetchFeed.apply(any[String]) returns List(new Feed)

val myWork = new MyWork(fetchFeed)

      

I am struggling with two solutions. Is this a common pattern like this when you write functional style code? Are there open source projects in this style that I can get some ideas from?

+3


source to share


2 answers


The style you described is not part of it, in part because of the problems you talked about. If you're trying to achieve a functional style, you're better off just using type-aliased functions.



// Alias the function type to a meaningful name
type FetchFeed = String => List[Feed]

// Declaring an implementation
val fetchFeed: FetchFeed = url => ...

// Nice type name to work with
class MyWork(fetchFeed: FetchFeed)

// Declaring a mock is still easy
new MyWork(_ => List(new Feed))

      

+2


source


Scala ( A => B

) functions can be thought of as equivalent to Java interfaces that define a single method apply(a: A): B

. So the style you are describing is not the same as:

  • Client depends on interface
  • The interface is implemented by a hidden concrete subclass


And that has been completely standard, educational Java style almost since Java was invented.

Back in the days when I was writing Java all day, I remember using the Hierarchy Show Eclipses Show shortcut to find the executable subclass.

+1


source







All Articles