By broadening my horizons with javascript together with my python experience I put some thought.
What's the purpose of type if the vision of an entity to an external client is via its interface ?
In static typed languages, the type has a very strong, central importance. Type and interface are strictly associated. For example, in java when you declare an interface FooIface and an object implement that interface, you cannot use it in a context requiring BarIface, even if the two are exactly the same in terms of methods, signatures and exceptions.
Not so in python. Even if two objects have completely different and unrelated types, as long as their interface is the same, they are totally and transparently interchangeable. If it quacks and walks like a duck, it's a duck. I can completely change the nature of an object by completely altering its interface at runtime, but it will preserve the original type.
This point of view is put to the extreme in javascript, where every object in any prototype chain is just that, an object. you ask the type of each object in javascript, and it will tell you just that, it's an object.
It appears to me that the concept of type for these languages is at the limit of futility. What is then really vital for ? Does type has a real meaning in dynamic typed languages?
I don't see futility. Consider:
1). When you construct an object
var myThing = new Thing( ... );
the Thing's type has significance.
2). A method of Thing can use
this.aProperty
according to its knowledge of type
3). You can use instanceof to determine a type
I tend to understand the word "type" as equivalent to the word "class" in Python. That's only 99% correct, but close enough.
>>> type(object)
<type 'type'>
>>> class X(object):
... pass
...
>>> type(X)
<type 'type'>
>>> type(_)
<type 'type'>
>>> type(X())
<class '__main__.X'>
>>> type(X) is type(type)
True
I do, however, usually avoid the word "type" in this case. In general, my way of seeing it is this: The word "type" implies that the thing in question is not a first-class object.
If a language only regards the implemented methods of a class to infer which interfaces it conforms to, you can implement an interface by accident. Lets say in Java you have the interfaces IA and IB which both define the method long getRemainingTime. In this case the contract of these interfaces would specify, what kind of format they would return (one could return the time in seconds, while the other returns the time in milliseconds). Also the context in which these interfaces are used can be very different. Lets say they are not called IA and IB but IProgress and IStopWatch. In such a case, the returned time would have very different meanings. If you were able to interchange these two interfaces as you liked, you might get really unexpected results.
In general the type can be seen as an aid to perform a rudimentary, static code analysis. If you implement a specific interface, the compiler can then tell you directly that you are probably making a mistake, if you try to pass an instance of your implementation to a method which expects a similar implementation but of a different type.
Related
I have read a lot about abstract data types (ADTs) and I'm askig myself if there are non-abstract/ concrete datatypes?
There is already a question on SO about ADTs, but this question doesn't cover "non-abstract" data types.
The definition of ADT only mentions what operations are to be
performed but not how these operations will be implemented
reference
So a ADT is hiding the concrete implementation from the user and "only" offers a bunch of permissible operations/ methods; e.g., the Stack in Java (reference). Only methods like pop(), push(), empty() are visible and the concrete implementation is hidden.
Following this argumentation leads me to the question, if there is a "non-abstract" data type?
Even a primitive data type like java.lang.Integer has well defined operations, like +, -, ... and according to wikipedia it is a ADT.
For example, integers are an ADT, defined as the values …, −2, −1, 0, 1, 2, …, and by the operations of addition, subtraction, multiplication, and division, together with greater than, less than, etc.,
reference
The java.lang.Integer is not a primitive type. It is an ADT that wraps the primitve java type int. The same holds for the other Java primitive types and the corresponding wrappers.
You don't need OOP support in a language to have ADTs. If you don't have support, you establish conventions for the ADT in the code you write (i.e. you only use it as previoulsy defined by the operations and possible values of the ADT)
That's why ADT's predate the class and object concepts present in OOP languages.They existed before. Statements like class just introduced direct support in the languages, allowing compilers to check what you are doing with the ADTs.
Primitive types are just values that can be stored in memory, without any other associated code. They don't know about themselves or their operations. And their internal representation is known by external actors, unlike the ADTs. Just like the possible operations. These are manipulations to the values done externally, from the outside.
Primitive types carry with them, although you don't necessary see it, implementation details relating the CPU or virtual machine architecture. Because they map to CPU available register sizes and instructions that the CPU executes directly. Hence the maximum integer value limits, for example.
If I am allowed to say this, the hardware knows your primitive types.
So your non-abstract data types are the primitive types of a language,
if those types aren't themselves ADT's too. If they happen to be ADTs,
you probably have to create them (not just declare them; there will
be code setting up things in memory, not only the storage in a certain
address), so they have an identity, and they usually offer methods
invoked through that identity, that is, they know about themselves.
Because in some languages everything is an object, like in Python, the
builtin types (the ones that are readily available with no
need to define classes) are sometimes called primitive too, despite
being no primitive at all by the above definition.
Edit:
As mentioned by jaco0646, there is more about concrete/abstract
words in OOP.
An ADT is already an abstraction. It represents a category
of similar objects you can instantiate from.
But an ADT can be even more abstract, and is referred as such (as
opposed to concrete data types) if you declare it with no intention of
instantiating objects from it. Usually you do this because other "concrete"
ADTs (the ones you instantiate) inherit from the "abstract" ADT. This allows the sharing and extension of behaviour between several different ADTs.
For example you can define an API like that, and make one or more different
ADTs offer (and respect) that API to their users, just by inheritance.
Abstract ADTs maybe defined by you or be available in language types or
libraries.
For example a Python builtin list object is also a collections.abc.Iterable.
In Python you can use multiple inheritance to add functionality like that.
Although there are other ways.
In Java you can't, but you have interfaces instead, and can declare a class to implement one or more interfaces, besides possibly extending another class.
So an ADT definition whose purpose is to be directly instantiated, is a
concrete ADT. Otherwise it is abstract.
A closely related notion is that of an abstract method in a class.
It is a method you don't fill with code, because it is meant to be filled by children classes that should implement it, respecting its signature (name and parameters).
So depending on your language you will find possible different (or similar) ways of implementing this concepts.
I agree with the answer from #progmatico, but I would add that concrete (non-abstract) data types include more than primitives.
In Java, Stack happens to be a concrete data type, which extends another concrete data type Vector, which extends an ADT AbstractList.
The interfaces implemented by AbstractList are also ADTs: Iterable, Collection, List.
a generic repository interface looks something like below :
public interface IRepository<T> where T : Entity
{
T Get(int key);
IQueryable<T> Get();
void Save(T obj);
void Delete(T obj);
}
Another way to achieve the similar functionality is using polymorphism as shown below
public interface IRepository
{
Entity Get(int key);
IQueryable<Entity> Get();
void Save(Entity obj);
void Delete(Entity obj);
}
In general my question would be in what scenarios or use cases we should use generics? Can generics be avoided completely if we use polymorphism. Or I am completely making non sense here and these 2 are completely unrelated.
The most crucial difference between your first and second example is called type safety.
I'm assuming that you are asking the question from the point of view of a statically-typed language like C# or Java.
In the version that uses generics, your compiler makes sure you always work with suitable types. In contrast, in the second version (the one that uses a more general type), you’d be expected to check that manually. Also, the compiler will constantly force you to cast your general type (e.g., Entity) to a more specific one (e.g., Customer) to use the services the object provides.
In other words, you have to fight the compiler all the time since it will consistently require that we cast types for it to be able to validate the code we write.
With Generics
The first example uses a type variable T at the interface level. It means that when you define a variable for this interface type (or implement it), you will also be forced to provide a type argument for T.
For example
IRepository<Customer> custRepo = ...;
This means that wherever T appears, it must be replaced by a Customer, right?
Once you define the type argument for T to be Customer, it is as if your interface declaration would change, in the eyes of the compiler, to be something like this:
public interface IRepository
{
Customer Get(int key);
IQueryable<Customer> Get();
void Save(Customer obj);
void Delete(Customer obj);
}
Therefore, when you use it, you would be forced by the compiler to respect your type argument:
Customer customer = custRepo.Get(10);
customer.setEmail("skywalker#gmail.com");
custRepo.Save(customer);
In the example above, all repository methods work only with the Customer type. Therefore, I cannot pass an incorrect type (e.g., Employee) to the methods since the compiler will enforce type safety everywhere. For example, contrast it with this other example where the compiler catches a type error:
Employee employee = empRepo.Get(10);
custRepo.Save(employee); //Uh oh! Compiler error here
Without Generics
On the other hand, in your second example, all you have done is decide that you’ll use a more generic type. By doing that, you sacrifice type safety in exchange for some flexibility:
For example:
IRepository custRepo = ...;
Entity customer = custRepo.Get(10);
((Customer) customer).setEmail("skywalker#gmail.com"); //Now you'll need casting
custRepo.Save(customer);
In the case above, you're forced to always cast your Entity to a more usable type like Customer to use what it offers. This casting is an unsafe operation and can potentially introduce bugs (if we ever make a mistake in our assumptions about the types we're using).
Also, the repository types do not prevent you from passing the wrong types to the methods, so you could make semantic mistakes:
Entity employee = (Employee) empRepo.Get(10);
custRepo.Save(employee); //Uh Oh!
If you do it this way, you will probably have to make sure in your CustomerRepo that your entity is that of a Customer to prevent a mistake like the one in the last line of the example above.
In other words, you would be manually implementing the kind of type safety that the compiler gives you automatically when you use generics.
This is starting to sound like we are trying to use our statically-typed language as if it was a dynamically-typed one, right? That's why we have to fight the compiler all the way to enforce this style of programming.
About Parametric Polymorphism
If you want, you could explore the idea that generics is also a form of polymorphism known as parametric polymorphism. I think reading this another answer could help as well. In it, there's a citation to an excellent paper on polymorphism that might help you broaden your understanding of the topic beyond just class and interface inheritance.
Dynamically-Type Languages vs. Statically-Typed Languages Debate
An exciting conclusion that might help you explore this further is that dynamic languages (e.g., JavaScript, Python, Ruby, etc.), where you don't have to make explicit type declarations, actually work like your generic-free example.
Dynamic languages work as if all your variables were of type Object, and they allow you to do anything you want with that object to avoid continually casting your objects to different types. It is the programmer's responsibility to write tests to ensure the object is always used appropriately.
There has always been a debate between defenders of statically-typed languages and those that prefer dynamically-typed languages. This is what we typically call a holy war.
I believe that this is a topic you may want to explore more deeply to understand the fundamental differences between your two examples and to learn how static typing and type safety from generics compares to the high flexibility of just using dynamic types.
I recommend reading an excellent paper called Dynamically–Typed Languages by Laurence Tratt from Bournemouth University.
Now, in statically-typed languages like C#, or Java, we are typically expected to exploit type safety as best as we can. But nothing prevents us from writing the code as you would do in a dynamic language; it is just that the compiler will constantly fight us. That’s the case with your second example.
If that's a way of programming that resonates more with you and your work style, or if it offers you the flexibility you seek, then perhaps you should consider using a dynamically-type language. Maybe one that can be combined on top of your current platform (e.g., IronRuby or IronPython) such that you can also reuse pre-existing code from your current statically-typed language.
In the discussion on The Myths of Object-Orientation, Tim Sweeney describes what he thinks is a good alternative to the all-encompassing frameworks that we all use today.
He seems most interested in typeclasses:
we can use constructs like typeclasses to define features (like persistence, introspection,
identity, printing) orthogonally to type constructs like classes and
interfaces
I am passingly familiar with type classes as "types of types" but I am not sure exactly how they would be applied to the fore-mentioned problems: persistence, printing, ...
Any ideas?
My best guess would be code reuse through default methods and orthogonal definition through detachment of type class implementation from type itself.
Basically, when you define type class, you can define default implementations for methods. For example Eq (equality) class in Haskell defines /= (not equal) as not (x == y) and this method will work by default for all implementation of the type class. In a similar way in other language you could define a type class with all persistence code written (Save, Load) except for one or two methods. Or, in a language with good reflection capabilities you could define all persistence methods in advance. In practice, it is kind of similar to multiple inheritance.
Now, the other thing is that you do not have to attach the type class to your type in the same place where you define your type, you can actually do it later and in a different place. This allows persistence logic to be nicely separated from the original type.
Some good examples in how that looks like in an OOP language are in my favorite paper ever: http://www.stefanwehr.de/publications/Wehr_JavaGI_generalized_interfaces_for_Java.pdf. Their description of default implementations and retroactive interface implementations are essentially the same language features as I have just described.
Disclaimer: I do not really know Haskell so I might be wrong in places
Do you know programming languages where changing the class of an object at runtime is allowed (supported)?
Please give a short example regarding the syntax. Give a use case, if you know any. Examples involving duck typing are welcome as well, so do not shy away from mentioning these languages.
Update: I figured out that Smalltalk has changeClassTo and become. CLOS can do change-class. I found a paper suggesting to use these mechanisms to implement 'husk objects' that are referenced at runtime, but only constructed from some persistence when actually accessed, providing some nifty lazy loading of related objects.
I assume, you mean the following:
You have an object of class A. But you would like to treat it as an object of class B.
There are some constructions possible:
If B is a subclass of A you can cast the object to B (but it should be created as B else you have unexpected (and hopefully unwanted) results).
In some languages you can cast anything to anything. If you know what you are doing, this is great, else prepare for several holes in your foot.
You mention ducktyping. I have no practical experience with it. But As far as I know, duck typing is something like this: "I need an object that support methods X, Y and Z." In that case you don't care about the class. You just want it to quack, swim and walk at your command.
Give a usecase
??? I'd expect you to ask for a solution on a specific use case.
Changing type of an object? I think "No."
But if you like to change part of an objects capabilities or behaviours have a look at loosely coupling!
For example your class holds a member of type File_Saver. There's a public setter accepting any instance of File_Saver and you can inject File_Saver_XML, File_Saver_PDF, ...
It's no common way, but any processing inside a class can be done by 1-n loosely coupled handlers, which you can exchange from outside.
Melt down to your question: You need a wrapper + a setter. :-)
Coming back to the case after some time, I've come to the conclusion that you want duck typing if you feel the need of changing an objects class.
Today I came to a fundamental paradox of the object programming style, concrete types or interfaces.
Whats the better election for a method's return type: a concrete type or an interface?
In most cases, I tend to use concrete types as the return type for methods. because I believe that an concrete type is more flexible for further use and exposes more functionality.
The dark side of this: Coupling.
The angelic one: A concrete type contains per-se the interface you would going to return initially, and extra functionality.
What's your thumb's rule?
Is there any programming principle for this?
BONUS: This is an example of what I mean ReadOnlyCollection or IEnumerable for exposing member collections?
My rules of thumb:
1) Initially, I have the method return the interface type, because its always easy to change it to the concrete type later if necessary. Harder to go back the other way.
2) Even if the method is declared to return the concrete type, I would code the callers to use the interface type whenever possible:
InterfaceType i = xyz.methodThatReturnsConcreteType();.
3) Whether I own the calling code makes a difference too (internal vs public APIs):
If I own the code that calls the method in question (i.e. internal API), then the more willing I am to return the concrete type.
If I don't control the code that calls this method (e.g. public API), the more likely I am to return the interface type instead. Returning the concrete type is a commitment and, generally speaking, the less I promise, the easier.
Other considerations:
Testing may be easier with interfaces since I can use a mock object that implements the interface.
There's an outside chance that I would want to return a proxy object (now I'm really reaching for excuses)
In summary,
I usually return the interface type because I feel the benefits of loose-coupling outweigh the convenience of having full access to the concrete type.
However, I'm not opposed to switching to return the concrete type on a case-by-case basis whenever the convenience outweighs the benefits of loose-coupling.
Rule of thumb, in return types, be a as specific as possible, in parameter types be as unspecific as possible. Also prefer interfaces, since you may later exchange your implementation if necesary, without changing the clients of your API.
Interesting question. I believe you have to ask yourself how can the return data be used. Using the age old car analogy if you had
public AccelerationResponse PressAccelerator(float force) {}
Chances are that you'd want to return an interface rather than a class. You could be interpreting this response differently depending on certain conditions.
If you are guaranteed that your return can only be used in the manner expected by the concrete implementation then using that class makes sense. I'm not sure of any widely accepted principle but my rule of thumb is if the return type can be reused in different implementations an interface makes more sense.