This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Creating an abstract class in Objective C
In Java I like to use abstract classes to make sure that a bunch of classes has the same basic behavior, e.g.:
public abstract class A
{
// this method is seen from outside and will be called by the user
final public void doSomething()
{
// ... here do some logic which is obligatory, e.g. clean up something so that
// the inheriting classes did not have to bother with it
reallyDoIt();
}
// here the actual work is done
protected abstract void reallyDoIt();
}
Now that if class B inherits from class A, it only has to implement reallyDoIt().
How to make this in Objective C? Is it at all possible? Is it feasible in Objective C? I mean the whole paradigm seems to be different in Objective C e.g. from what I understand there is no way to forbid overriding a method (like in Java with 'final')?
Thanks!
There is no actual constraint on not overriding a method in objective c. You can use a protocol as Dan Lister suggested in his answer but this is only good to enforce your conforming class to implement a certain behavior declared in that protocol.
A solution for an abstract class in objective c could be :
interface MyClass {
}
- (id) init;
- (id) init {
[NSException raise:#"Invoked abstract method" format:#"Invoked abstract method"];
return nil;
}
This way you can prevent methods in your abstract class to be invoked (but only at run-time unlike languages like java which can detect this when on compile-time).
You'll want to use something called Protocols I think.
Related
I'd like to implement some interface methods in another file, using extensions.
I have a feeling it's not possible, but I'd love to do that.
Is this possible?
Here is the idea :
MyClass.kt
class MyClass : MyInterface {
}
MyClassExtension.kt
override MyClass.MyInterface.method1() {
}
override MyClass.MyInterface.method2() {
}
That is not possible to implement the interface in the other file. There are still some possibilities.
You may split your implementation into several abstract classes, e.g. abstract class A : Interface, abstract class B : A and so on. Each class can be in its own file.
The second alternative, that does not let one implement an interface, rather split method implementations is called extension functions.
https://kotlinlang.org/docs/reference/extensions.html
Extension functions are only able to access public API of a class. Extension functions cannot implement interface methods in that case.
Use the following syntax for the declaration:
fun MyClass.method2() { ... }
I want to override toString() in an interface and have objects that implement that interface to default to using that method (eg: not shadowed)
interface SingletonObjectTrait {
fun toString(): String = this.javaClass.simpleName
}
Is there a straightforward way to define such an interface, preferably with minimal configuration at implementation
object MyEvent: SomeEventLogic(), SomeEventType, SingletonObjectTrait
class SomeEventLogic {}
interface SomeEventType {}
That's not possible, I'm afraid.
Method implementations in interfaces work much like default methods in Java: they're used only if the implementing class doesn't have an implementation already. But every class already inherits toString() from Any, so the default would never be used.
In fact, the compiler has a specific error for this — if you try to implement toString() in an interface, it says:
An interface may not implement a method of 'Any'
I can't see a good way around this.
As Erik says, one option is to change the interface to an abstract class; but of course that's not viable if any implementations already extend another class.
Another option might be to implement a different method in the interface, and in the comments instruct implementing classes to override toString() and call that method. Not automatic, but less work for implementers, and less repetition.
There isn't a great way to do this other than using maybe an annotation processor to add the missing override at compile time (by adding an annotation to the interface that you detect and you generate the overrides in the implementation class). This would work, but may be biting off more than you want to, and is likely out of scope of an answer here on Stack Overflow (seek "how to write an annotation processor for Java or Kotlin" and "KAPT" for the one engine that supports Kotlin processors).
Back to your code and why it will not work as-is:
An interface cannot have a method with a signature that matches any of the methods in Any class. And if you try to override one of them you will get a compilation error.
An interface may not implement a method of 'Any'
The minimal code to do something like you want is:
interface SingletonObjectTrait {
fun asString(): String = this.javaClass.simpleName
}
open class SomeEventLogic {}
interface SomeEventType {}
object MyEvent: SomeEventLogic(), SomeEventType, SingletonObjectTrait {
override fun toString(): String = asString() // hope they don't forget to call this!
}
There is no guarantee the implementer will call the trait asString() function but at least you can share the functionality with a one-liner in the implementing class.
How can I solve the following case?
interface I
class A(i: I)
class C : I, A(this) // << --- 'this' is not defined in this context
In short, I want to pass the class instance to super class constructor.
Is it possible in Kotlin?
P.S.
All the answers are good and technically correct. But let's give a concrete example:
interface Pilot {
fun informAboutObstacle()
}
abstract class Car(private val pilot: Pilot) {
fun drive() {
while (true) {
// ....
if (haveObstacleDetected()) {
pilot.informAboutObstacle()
}
// ....
}
}
fun break() {
// stop the car
}
}
class AutopilotCar : Pilot, Car(this) { // For example, Tesla :)
override fun informAboutObstacle() {
break() // stop the car
}
}
This example don't look too contrived, and why can't I implement it with OOP-friendly language?
No, this is not possible on the JVM. this is only available after the super class has been initialized.
From
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.10.2.4
The instance initialization method (§2.9.1) for class myClass sees the new uninitialized object as its this argument in local variable 0. Before that method invokes another instance initialization method of myClass or its direct superclass on this, the only operation the method can perform on this is assigning fields declared within myClass.
So the bytecode instruction aload 0 to push this on the stack is forbidden before the super-class constructor is called. That's why it cannot be passed as an argument to the super-constructor.
Kotlin was born as a JVM language and aims for maximum interoperability with Java code and a minimum overhead of its language features. While Kotlin could have chosen to orchestrate object initialization in a different way, it would create problems in mixed Java-Kotlin class hierarchies and add significant overhead.
In the good tradition of OOP languages such as Java, C# or Swift, Kotlin doesn't allow you to leak the this reference before the call to superclass initialization has completed. In your special case you're just storing the reference, but in just a slightly different case the superclass code might try to use the received object, which at that point is still uninitialized.
As a specific example of why languages don't allow this, consider a case where A is a class from a library you use and this rule is not in effect. You pass this like you do and things work fine. Later you update the library to a newer version and it happens to add something as benign as i.toString() to its constructor. It has no idea it's actually calling an overridden method on itself. Your toString() implementation observes all its invariants broken, such as uninitialized vals.
This design suffers from other problems, not just the circular initialization dependency you are struggling with now. In a nutshell, the class A expects this:
But instead you create this:
The class A has a dependency on a collaborator object of type I. It doesn't expect itself as the collaborator. This may bring about all kinds of weird bugs. For example your C.toString() may delegate to super.toString() and A.toString() (A is the super of C) may call into I.toString(), resulting in a StackOverflowError.
I can't say from your question whether A is designed for extension, which would make the C : A part correct, but you should definitely disentangle A from I.
I am just reading Dart language specification and exploring a new interesting language. As Dart language specification says: Dart has implicit interfaces. Which means every class is an interface too. So, If I want to implement some behavior of another class, implements clause is the only I need.
Also, Dart supports mixins. So that we can take implementation of methods from another class using with keyword.
So, given that if an abstract class A defines method a() like :
abstract class A {
void a();
}
and another two concrete class B defines method a() but does not implements class A like:
class B {
void a() {
print("I am class B");
}
}
and class C implements class A with Mixin B like :
class C extends Object with B implements A {
...
}
Here, I have few questions about it. If a class implements the interface and also use mixin that has method implementation with same method name; doesn't it would make cycling inheritance possible?
What will be the behaviour of class C? Does it need to implement a() or it will be implicitly implemented by mixin B?
I am just learning Dart and concepts like mixins are very unfamiliar to me. Can anyone help me understanding by answering my questions?
Mixins are a kind of limited multiple inheritance. With C with B, C inherits an implementation of void a(). Adding implements A doesn't need anything more to be done, because C already fulfills the contract it claims to fulfill by implements A, because of B.
Your link is to the Language Tour, not the specification, but the tour is definitely what you should be reading to start with.
Your example is just fine. class C extends Object with B { ... } basically adds the members of B to Object to create C. If C then satisfies the interface A it can declare support for that interface ( implements A ).
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I seem to run into this situation quite a lot and have yet to find a solution that I find acceptable.
Quite often I will have parallel inheritance hierarchies where a method in one hierarchy gets passed the matching class from the other hierarchy as a parameter.
Here is an example that probably explains this better.
abstract class Animal
{
public virtual void Eat(Food f)
{
}
}
abstract class Food
{
}
class LionFood : Food
{
}
class ElephantFood : Food
{
}
class Lion : Animal
{
public override void Eat(Food f)
{
// It is only ever valid to pass LionFood here as the parameter.
// passing any other type of Food is invalid and should be prevented
// or at least throw an exception if it does happen.
}
}
In the past, I have usually made the base class generic to allow the implementing concrete class to define the type as follows..
abstract class Animal<T> where T : Food
{
public abstract void Eat(T f);
}
class Lion : Animal<LionFood>
{
public override void Eat(LionFood f)
{
}
}
At first this seems like a very good solution because it provides compile-time type safety. But the more I use it, the more I am starting to think that using generics in this way is infact an anti-pattern. The problem is that the Animal base class cannot be used in a polymorphic way. You cannot, for example, easily write a method that will process any type of Animal regardless of its actual concrete type.
Every time I use this generics solution, I always seem to end up with covariant and contravariant interfaces all over the place just to try and provide the polymorphic behaviour I want. This gets out of hand pretty quickly and some functionality is not possible simply because the correct interface cannot be provided.
Of course another option is to not use generics and perform runtime type checking in the Eat method like this:
public override void Eat(Food f)
{
if (f.GetType() != typeof(LionFood))
{
throw new Exception();
}
}
This is better than nothing I suppose but I'm not a huge fan of it simply because of the lack of compile-time type safety.
So after all that.. My question is.. What is the best practice to provide polymorphic behaviour while at the same time ensuring some type safety?
Is there some OO design trick or pattern that I am missing that will allow me to avoid the parallel inheritance hierarchies all together?
I appreciate that this question is somewhat subjective, but there are points available for everyone who contributes and I'll choose the best response as the answer.
Thanks for looking.
Edit:
Having thought about this I realise that my example given doesn't really make sense. Of course it is not possible to use Animal in a polymorphic way because the type passed to Eat will always depend on the actual underlying type of Animal (which the initiator of a polymorphic call will not know)! I need to think of a better example that illustrates my actual situation.
I think common sense and the requirements of the domain will dictate the proper approach. Working with this example, I'd do like this
public class Lion:Animal
{
public override void Eat(Food f)
{
Eat(f as LionFood);
}
public void Eat(LionFood food)
{
//check for null food
//actually consume it
}
}
Edit
I think using generics is not suited in this case, because what if an Animal can play with a Toy, hunt a specific Animal and so on. You can have a number of methods with arugments that implement an abstraction, it's awkward to use generics every time there is a method with an argument that uses polymorhpism.
Ok, could that be what you want? Sometimes, when you can't articulate what you want to do, what you want is actually a mixin.
template<typename base>
class Eater: public base {
template<typename T>
Eat(T (extends Food) food) { // you can do that extends thing in C++ but I won't bother
// register what's eaten, or do whatever
base::Eat(food);
}
}
class Lion {
Eat(LionFood food) {
cout<<"Hmm delicious!";
}
}
int main() {
Eater<Lion> lion;
lion.eat(LionFood());
return 0;
}
This'll give you a nice compiler error if you try to feed grass to the lion.