How do you declare an interface in Rust? - interface

I have multiple types with similar methods. I want to abstract over them by writing an interface, like I would in Java:
public interface Shape {
public float area();
}
class Circle implements Shape {
public float area() {
return radius * radius * Math.PI;
}
public float radius;
}
However, there is no interface keyword in Rust. Doesn't Rust offer the possibility to abstract over multiple types?

TL;DR: The closest to interface in Rust is a trait. However, do not expect it to be similar in all point to an interface. My answer does not aim to be exhaustive but gives some elements of comparison to those coming from other languages.
If you want an abstraction similar to interface, you need to use Rust's traits:
trait Shape {
fn area(&self) -> f32;
}
struct Circle {
radius: f32,
}
impl Shape for Circle {
fn area(&self) -> f32 {
self.radius.powi(2) * std::f32::consts::PI
}
}
struct Square {
side: f32,
}
impl Shape for Square {
fn area(&self) -> f32 {
self.side.powi(2)
}
}
fn main() {
display_area(&Circle { radius: 1. });
display_area(&Square { side: 1. });
}
fn display_area(shape: &dyn Shape) {
println!("area is {}", shape.area())
}
However, it is an error to see a Rust trait as an equivalent of OOP interface. I will enumerate some particularities of Rust's traits.
Dispatch
In Rust, the dispatch (i.e. using the right data and methods when given a trait) can be done in two ways:
Static dispatch
When a trait is statically dispatched, there is no overhead at runtime. This is an equivalent of C++ templates; but where C++ uses SFINAE, the Rust compiler checks the validity using the "hints" we give to him:
fn display_area(shape: &impl Shape) {
println!("area is {}", shape.area())
}
With impl Shape, we say to the compiler that our function has a generic type parameter that implements Shape, therefore we can use the method Shape::area on our shape.
In this case, like in C++ templates, the compiler will generate a different function for each different type passed in.
Dynamic dispatch
In our first example:
fn display_area(shape: &dyn Shape) {
println!("area is {}", shape.area())
}
the dispatch is dynamic. This is an equivalent to using an interface in C#/Java or an abstract class in C++.
In this case, the compiler does not care about the type of shape. The right thing to do with it will be determined at runtime, usually at a very slight cost.
Separation between data and implementation
As you see, the data is separated from the implementation; like, for example, C# extension methods. Moreover, one of the utilities of a trait is to extend the available methods on a value:
trait Hello {
fn say_hello(&self);
}
impl Hello for &'static str {
fn say_hello(&self) {
println!("Hello, {}!", *self)
}
}
fn main() {
"world".say_hello();
}
A great advantage of this, is that you can implement a trait for a data without modifying the data. In contrast, in classical object oriented languages, you must modify the class to implement another interface. Said otherwise, you can implement your own traits for external data.
This separation is true also at the lowest level. In case of dynamic dispatch, the method is given two pointers: one for the data, and another for the methods (the vtable).
Default implementation
The trait has one more thing than a classic interface: it can provide a default implementation of a method (just like the "defender" method in Java 8). Example:
trait Hello {
fn say_hello(&self) {
println!("Hello there!")
}
}
impl Hello for i32 {}
fn main() {
123.say_hello(); // call default implementation
}
To use classic OOP words, this is like an abstract class without variable members.
No inheritance
The Rust trait's system is not an inheritance system. You cannot try to downcast, for example, or try to cast a reference on a trait to another trait. To get more information about this, see this question about upcasting.
Moreover, you can use the dynamic type to simulate some behavior you want.
While you can simulate the inheritance mechanism in Rust with various tricks, this is a better idea to use idiomatic designs instead of twist the language to a foreign way of thinking that will uselessly make grow the complexity of code.
You should read the chapter about traits in the Rust book to learn more about this topic.

Related

Why can't the parameter type of a #override method be “tighten” in Dart?

Background
I am new to Dart and recently I've been reading some docs about Dart sound type system until I ran into a section called Use sound parameter types when overriding methods
It states that
The parameter of an overridden method must have either the same type
or a supertype of the corresponding parameter in the superclass. Don’t
“tighten” the parameter type by replacing the type with a subtype of
the original parameter.
and shows me a block of code saying
What I am confused of
My question is that, of course, by prohibiting parameter type "tighten" in an override method we can prevent
define a cat and send it after an alligator
class Animal {
chase(Animal a) {}
}
class Mouse extends Animal {}
class Alligator extends Animal {}
class CatA extends Animal {
#override
// error on this line
void chase(Mouse x) {} // It makes sense. Cat chases Mouse
}
class CatB extends Animal {
#override
// error on this line
void chase(Alligator x) {} // Cat chases Alligator ? You can't be serious!
}
But how about using a Object(witch is the supertype of almost all others) as its parameter type
class Cat extends Animal {
#override
void chase(Object x) { // Now this Cat can chase anything.....
}
}
void main() {
var cat = Cat();
cat.chase(Alligator()); // Again, we are trying to let a little pussy chase a terrifying beast!
}
// This piece of code works
What is it all about, this does not makes sense to me at all...Furthermore, what if I create a supercat that extends a Cat, which can indeed chase after a Alligator
class SuperCat extends Cat {
#override
// error on this line
void chase(Alligator x) { // I make a SuperCat chasing after a Alligator intentionally, but it doesn't work...
}
}
These things above are really blowing my minds off, do I get it wrong in some way or is there anything more under the hood that makes it this way?
Update
Thanks to #jamesdlin and #Abion47, I could finally figure out most of the puzzles, but there is still one more problem to solve. As #jamesdlin mentioned, contract of the base class method must be honored when overriding a method. Taking Animal and Cat for example, Animal.chase makes a contract saying chase must be compatible to accept any Animal, no matter it is Alligator or
Mouse, but does this contract also make a restrction that chase must not be able to accept any other Object excepts for Animal?(It is natural to think about it because you can't pass a casual Object parameter into Animal.chase) And if it does, why does Dart allow widening Cat.chase parameter type from Animal to Object? Doesn't it violate the contract made by Animal.chase?
The answer referenced by jamesdlin has the details of why this isn't allowed, but I'll try to give a nutshell version.
abstract class Animal {
void chase(Animal a) { ... }
}
class Mouse extends Animal {}
class Alligator extends Animal {}
class Cat extends Animal {
#override
void chase(Mouse x) { ... } // No-no
}
In theory, this would be fine, since Mouse extends Animal and Cat is just restricting what kind of animal can be passed to chase.
But think about what happens with polymorphism. The hard rule is that any classes that extend and override a base class must be compatible with that base class. That ensures that, even if the function is called on a handle that is typed to the base class, it is guaranteed that the call will go to the correct function definition in the overriding class.
This is what makes abstract classes possible - if there was an implementation of a function in a derived class that wasn't compatible with the same function in the base class, it would be impossible to treat instances of inherited classes as though they were instances of the base class.
For example, take the example from the article but instead of explicitly creating a Cat, have it be some randomly generated animal:
Animal a = RandomAnimalFactory.create();
a.chase(Alligator());
What is the exact type of a? You have no way of knowing. All you know is that it is some subtype of Animal.
Now look at the call to a.chase(Alligator()). Would that succeed? Well, yes, because Animal.chase requires an Animal and Alligator is an Animal. No problems there.
But imagine if a subclass could restrict the type of that parameter, e.g. if Cat could restrict it to Mouse. Now it's unclear whether that call would succeed because even though you know that a is an Animal, you don't know what kind of Animal. What if it's a type that makes Alligator no longer a valid parameter? In order to know, the type system would have to unpack the declared type of the variable to examine the actual type, and only then would it know whether the call would succeed. This flies in the face of inheritance, where a type that extends a base type can be interchangeable with any of its sibling types.
All of a sudden, what used to be a simple matter has become extremely complex. Not only does it make the implementation of an OOP-based type system astronomically more complicated, it completely undermines the point of inheritance.

Scala: Using self types to implement a strategy pattern

I'm attempting to implement a strategy pattern for a class I have that manages state. The strategy implementations should have access to the protected/public members of the class which uses those strategies, and the class using the strategies needs access to the public members of the strategy.
I've got this working, except I can't really figure out how to do this without creating different top-level classes per-strategy. Here is an example:
class BranchState(a: String, b: Int) extends ABranchState(a, b) with QueuedStrat
class ABranchState(a: String, b: Int) {
this: ChainingStrategy =>
.... lots of impl ....
}
trait ChainingStrategy {
self: BranchState =>
... headers only, no impl ...
}
trait QueuedStrat extends ChainingStrategy {
self: BranchState =>
.... impl ....
}
trait AnotherStrat extends ChainingStrategy {
self: BranchState =>
.... impl ....
}
The problem here is if I want to instantiate a BranchState with uses AnotherStrat, I have to make another class. I've tried to add a type parameter to BranchState like [T <: ChainingStrategy] but that doesn't work because the compiler (rightfully) complains I have to have implementations for the headers in ChainingStrategy. It seems like I need some mechanism to say "some type which implements chaining strategy fully, IE: has no unimplemented methods".
Maybe that's just not the right way at all, though. How can I accomplish this?
Thanks
I don't think what you are trying to do does make any sense in term of design. You are trying to treat your strategies as if they were states. But a Strategy is not any specialization or generalization of a State, so I don't think they should have any inheritance relationship.
Moreover, in Scala one should not be needing the Strategy Pattern, due to the functional aspect of the language, you could take a real advantage of Higher-order Functions (I recommend you to read: How Scala killed the Strategy Pattern, Alvin Alexander).
I hope this helps you!

Object extends Trait, Class extends Trait, both have to implement method

I have the following setup:
trait A
{
def doSomething(): Unit;
}
object B extends A
{
override def doSomething(): Unit =
{
// Implementation
}
}
class B(creator: String) extends A
{
override def doSomething(): Unit =
{
B.doSomething() // Now this is just completely unnecessary, but the compiler of course insists upon implementing the method
}
}
Now you may wonder why I even do this, why I let the class extend the trait as well.
The problem is, that somewhere in the Program there is a Collection of A.
So somewhere:
private val aList: ListBuffer[A] = new ListBuffer[A]
and in there, I also have to put Bs (among other derivates, namely C and D)
So I can't just let the B-class not extend it.
As the implementation is the same for all instances, I want to use an Object.
But there is also a reason I really need this Object. Because there is a class:
abstract class Worker
{
def getAType(): A
def do(): Unit =
{
getAType().doSomething()
}
}
class WorkerA
{
def getAType(): A =
{
return B
}
}
Here the singleton/object of B gets returned. This is needed for the implementation of do() in the Worker.
To summarize:
The object B is needed because of the generic implementation in do() (Worker-Class) and also because doSomething() never changes.
The class B is needed because in the collection of the BaseType A there are different instances of B with different authors.
As both the object and the class have to implement the trait for above reasons I'm in kind of a dilemma here. I couldn't find a satisfying solution that looks neater.
So, my question is (It turns out as a non-native-speaker I should've clarified this more)
Is there any way to let a class extend a trait (or class) and say that any abstract-method implementation should be looked up in the object instead of the class, so that I must only implement "doSomething()" (from the trait) once (in the object)? As I said, the trait fulfills two different tasks here.
One being a BaseType so that the collection can get instances of the class. The other being a contract to ensure the doSomething()-method is there in every object.
So the Object B needs to extend the trait, because a trait is like a Java interface and every (!) Object B (or C, or D) needs to have that method. (So the only option I see -> define an interface/trait and make sure the method is there)
edit: In case anyone wonders. How I really solved the problem: I implemented two traits.
Now for one class (where I need it) I extend both and for the other I only extend one. So I actually never have to implement any method that is not absolutely necessary :)
As I wrote in the comment section, it's really unclear to me what you're asking.
However, looking at your code examples, it seems to me that trait A isn't really required.
You can use the types that already come with the Scala SDK:
object B extends (()=>Unit) {
def apply() { /* implementation */ }
}
Or, as a variant:
object B {
val aType:()=>Unit = {() => /* implementation */ }
}
In the first case, you can access the singleton instance with B, in the second case with B.aType.
In the second case, no explicit declaration of the apply method is needed.
Pick what you like.
The essential message is: You don't need a trait if you just define one simple method.
That's what Scala functions are for.
The list type might look like this:
private val aList:ListBuffer[()=>Unit] = ???
(By the way: Why not declare it as Seq[()=>Unit]? Is it important to the caller that it is a ListBuffer and not some other kind of sequence?)
Your worker might then look like this:
abstract class Worker {
def aType:()=>Unit // no need for the `get` prefix here, or the empty parameter list
def do() {aType()}
}
Note that now the Worker type has become a class that offers a method that invokes a function.
So, there is really no need to have a Worker class.
You can just take the function (aType) directly and invoke it, just so.
If you always want to call the implementation in object B, well - just do that then.
There is no need to wrap the call in instances of other types.
Your example class B just forwards the call to the B object, which is really unnecessary.
There is no need to even create an instance of B.
It does have the private member variable creator, but since it's never used, it will never be accessed in any way.
So, I would recommend to completely remove the class B.
All you need is the type ()=>Unit, which is exactly what you need: A function that takes no parameters and returns nothing.
If you get tired of writing ()=>Unit all the time, you can define a type alias, for example inside the package object.
Here is my recommentation:
type SideEffect = ()=>Unit
Then you can use SideEffect as an alias for ()=>Unit.
That's all I can make of it.
It looks to me that this is probably not what you were looking for.
But maybe this will help you a little bit along the way.
If you want to have a more concrete answer, it would be nice if you would clarify the question.
object B doesn't really have much to do with class B aside from some special rules.
If you wish to reuse that doSomething method you should just reuse the implementation from the object:
class B {
def doSomething() = B.doSomething()
}
If you want to specify object B as a specific instance of class B then you should do the following:
object B extends B("some particular creator") {
...
}
You also do not need override modifiers although they can be handy for compiler checks.
The notion of a companion object extending a trait is useful for defining behavior associated with the class itself (e.g. static methods) as opposed to instances of the class. In other words, it allows your static methods to implement interfaces. Here's an example:
import java.nio.ByteBuffer
// a trait to be implemented by the companion object of a class
// to convey the fixed size of any instance of that class
trait Sized { def size: Int }
// create a buffer based on the size information provided by the
// companion object
def createBuffer(sized: Sized): ByteBuffer = ByteBuffer.allocate(sized.size)
class MyClass(x: Long) {
def writeTo(buffer: ByteBuffer) { buffer.putLong(x) }
}
object MyClass extends Sized {
def size = java.lang.Long.SIZE / java.lang.Byte.SIZE
}
// create a buffer with correct sizing for MyClass whose companion
// object implements Sized. Note that we don't need an instance
// of MyClass to obtain sizing information.
val buf = createBuffer(MyClass)
// write an instance of MyClass to the buffer.
val c = new MyClass(42)
c.writeTo(buf)

Creating a monad for repeating methods

I'm trying to understand what monads are in Scala.
Say for example I have methods in Java like this:
public void doSomeThing()
{
a.call();
}
public void doOtherThing()
{
a2.call();
}
public void doSomeOtherThing()
{
a3.call();
}
All the methods that starts with do, just only do the method call named call. If I convert that into a common method in Java like:
public void doGeneric(SomeClass a)
{
a.call();
}
and say this as a generic method, with does the call function, then doGeneric is an monad? Correct me if I'm wrong.
Note that I gave the examples in Java, as I'm just now starting with Scala.
Monad is associated to the notion of "container" like Option or List.
Basically, a container that defines the flatMap method is a monad:
trait Monad[A] { //let's say a Monad container to be general. A well-known would be Option
def flatMap[B](f: A => Monad[B]): Monad[B]
}
In your case, you simply call a method on one object.
You are not computing a "container"'s value from another container, so you haven't got a monad.
Indeed, you just make use of polymorphism.

when to use singleton objects and when to use actual objects in scala

I would like to know if there is any specific rule or if there is a rule of thumb to be followed on using actual objects in scala vs singleton objects in scala
say i have a class like this
class GetDataInput {
def getNameInput() {
println("Enter the name value: ")
}
def getTypeInput() {
println("Enter the type value: ")
}
def getBothInput() {
println("Enter the name value: ")
println("Enter the type value: ")
}
}
is it better to use it in regular terms like
val someval = new GetDataInput()
someval.getNameInput()
or is it good to create a singleton object for this class and access the methods using that
object GetDataInput {
def getNameInp() = getNameInput()
}
Any pointers on this?
Generally you make an object when:
It makes absolutely no sense of having different instances of a potential class, for example, to enclose several pure functions (like methematical functions, factory methods)
You want to write the equivalent of java static method or static final constants. (see Companion objects).
You want a simpler alternative for enum values (a sealed trait extended by objectinstances).
In your example, all the functions are pure, and the class is stateless. Therefore all instances will be strictly equal. It makes sense to turn it into an object:
object GetDataInput {
def getNameInput() {
println("Enter the name value: ")
}
...
}
If you made the wrong choice, don't worry, it is easy to refactor. Usually you can keep all existing calls to the object, simply by extracting the methods in a trait:
trait GetDataInput {
def getNameInput() {
println("Enter the name value: ")
}
}
object GetDataInput extends GetDataInput //Bring all traits methods into the object
// to keep previous behaviour
class MyGetDataInput( whatever: Foo ) extends GetDataInput {
...
}
The question is rather: "Do you need different instances of a type?" If so, then go for a class (or a trait), if not go for a singleton. And btw there are no specific guidelines for the language you are using only because it has the singleton pattern built into it.
In scala, one primary use of objects is to fill the role of singletons. If you want to use a class as a singleton, just declare the class itself as an object. Then you could do:
GetDataInput.getNameInput()
Internally, scala will lazily create a single instance of your class and keep it alive for the duration of the program, so anytime you call a method on the object, you're really calling methods of a singleton instance of the class managed by the scala runtime.