OOP Untangled Part 3: Other Languages Worth Mentioning

By Mohammed A.
Jul 04, 2021 • 5 mins read

In the previous articles, we used some well-known languages that were known for the OOP to achieve object orientation according to Alan Kay’s definition. In fact, there are other few some of them are not known for OOP, but we can still achieve object orientation with, which is what we’re discovering in this article.

This is the 3rd part of a series of articles, to check the other parts:

OOP Untanged Part 1: Object-Orientation and Dynamic Languages

OOP Untangled Part 2: Object-Orientation and Statically Typed Languages

The First Language

There’s a couple of statically typed languages that has interesting features that might ease the OOP. Take a look at this code:

class Record
  def save
    puts "saved!"
  end
end

class XeroIntegration
  def save_record(r)
    r.save
  end
end

class QuickbooksIntegration
  def save_record(r)
    r.save
  end
end

def somehow_get_integration_by_id(integration_id)
  case integration_id
  when "xero"
    XeroIntegration.new
  when "quickbooks"
    QuickbooksIntegration.new
  else
    raise "Unknown Integration" # To avoid nil
  end
end

r = Record.new

integration = somehow_get_integration_by_id("xero")
integration.save_record(r)

What do you think? What language is this? Well, if you say, Ruby, you’re very close, it’s actually a valid Ruby code. But this is Crystal language. It’s heavily inspired by Ruby (that’s why I like it) with static typing that can be inferred. Also, you can do duck typing!

The Second Language

Another interesting type system you can find in Go language—even though it’s not known for being a “full” object-oriented language. One of my favorite features in Go is that the interfaces are implicitly implemented if the struct has that method. Not clean what it means right? Let’s see some code!

type Record struct{}
func (self *Record) Save() {
	println("saved!")
}

type XeroIntegration struct{
    name string
}
func (self *XeroIntegration) SaveRecord(record interface{ Save() }) error {
	// Some logic here
	record.Save()
	return nil
}

type QuickbooksIntegration struct{
    name string
}
func (self *QuickbooksIntegration) SaveRecord(record interface{ Save() }) error {
	// Some logic here
	record.Save()
	return nil
}


// Another file
type Integration interface {
	SaveRecord(record interface{ Save() }) error
}

func SomehowGetIntegrationById(id string) (error, Integration) {
	switch id {
	case "xero":
		return nil, &XeroIntegration{}
	case "quickbooks":
		return nil, &QuickbooksIntegration{}
	default:
		return errors.New("Unknown Integration"), nil
	}
}

// Where it actually get used
func main() {
    // Returns something that support SaveRecord message
	err, integration := SomehowGetIntegrationById("xero")

	if err == nil {
		r := &Record{}
		integration.SaveRecord(r)
	}
}

Let’s ignore the part where it needs & and *. The implicit interface is a nice feature, as long as it supports those specific messages, it is accepted. No need to wrap the external integration or the one written by a teammate. Also, no need to extract the interface into its own package.

There’s one thing I didn’t like, the interfaces only work with method—which makes perfect sense. However, in contrast to Crystal (or Ruby) structs in Go exposes some fields—like the name above—that are not “methods”. To work around this, you might need to write a reader method for each field you have and keep the field private (starts with lowercase). Like the example below:

func (self *XeroIntegration) Name() string {
	return self.name
}

func (self *Quickbooks) Name() string {
	return self.name
}

Keep in mind, there might be other statically typed languages that I don’t know about their existence, that support features that are even more suited for OOP. I only mentioned the ones I follow and am aware of.

Conclusion

In this article, we discovered a different yet interesting set of languages that you can still achieve Alan Kay’s object orientation with, if I found more, I will surely add them, one I am thinking of is Clojure, but I don’t know the language yet, but I would love to implement OOP with it.

Hope you enjoyed the reading, see you in future articles!