-2

In short, I want all of my objects that implement an interface to have a common field. I have an interface called IMovable and I want every object that implements it to have a public field called hasMoved. In other words, I want all objects to have a field as if they inherited it from a class, but I want to implement multiple different interfaces and I don't want to have a class hierarchy. What would be the best way to solve this? Should I use properties? It's my first time using interfaces and I am not sure if they are the right solution to something like this.

phantasm
  • 7
  • 1
  • 2
    Why do you want them to have a particular private field if you aren't going to access it? – Lee May 17 '19 at 14:12
  • 3
    "I've also considered using a property, but that seems unreasonable, as I don't want any extra functionality." Can you explain that more? Why is an interface with a get-only property called `HasMoved` not work for you? Why is requiring a private field useful in the first place? – Sweeper May 17 '19 at 14:12
  • 5
    This seems like a classic exemple of an [XY Problem](http://xyproblem.info/). But why an abstract class wouldn't work with multiple interfaces? – Justin Lessard May 17 '19 at 14:12
  • 3
    A private field is an implementation-detail. Thus it´s never part of an interface. Why do you care for private at all? – MakePeaceGreatAgain May 17 '19 at 14:13
  • 1
    You are asking for the impossible. Interfaces cannot have fields. Methods with auto get;set; automatically create backer fields for you. – DrDoomPDX May 17 '19 at 14:15
  • 1
    What is the point of a common private field? The whole point of an interface is to have a common *public* set of members. – DavidG May 17 '19 at 14:17
  • 1
    Even if you **could** do this, how would you **use** that field? You would have to force your implementing class to also make use of he field, which you can´t. Your class is free to **not** use the field, even if it is there. – MakePeaceGreatAgain May 17 '19 at 14:19
  • Sorry, I am new to OOP. I meant that I want a public field, that would be on every object that implements the interface. I don't want inheritance, because I want objects to use multiple interfaces. I want to easily check if the object implements the IMovable interface, so that I can be sure that it has the hasMoved field. Is there an alternative way to do this? – phantasm May 17 '19 at 14:25
  • 2
    Then just add a property to your interface. – Justin Lessard May 17 '19 at 14:25
  • @JustinLessard: I'm just explaining OP's statement (which he is somewhat correct on, even if for the wrong reasons) Each interface would require its own abstract class to define that particular field, but a given concrete class can only inherit from one abstract class, thus making it impossible to enforce two different private fields (from different interfaces) to be implemented on that concrete class. It would require OP to make a new abstract class for every possible combination of interfaces, which is a futile exercise. – Flater May 17 '19 at 14:47
  • @Flater Yes, that is what I meant. I am very sorry for being unclear. I have edited my question. – phantasm May 17 '19 at 14:50

4 Answers4

1

I want every object that implements it to have a private field called _hasMoved

private field can't be made since interfaces will have all as public as it's a contract. You can't even go by an abstract class since private members are not inherited.

What if you make it a public field and have that contract in your interface

public interface IMovable
{
  bool HasMoved { get; set; }
}
Rahul
  • 76,197
  • 13
  • 71
  • 125
  • Seems like OP doesn´t want a property as "it´s overkill". – MakePeaceGreatAgain May 17 '19 at 14:15
  • @HimBromBeere: That's a fairly strict reading of OP's actual intent, since the answer to that is that interfaces don't define fields (even if public). While that is sort of what OP is expecting, it's reasonable to assume that OP is aware that since his exact expectation is impossible, _something_ has got to give. – Flater May 17 '19 at 14:35
  • 1
    Small correction: private members are inherited, buy derived types don't have access to them. – Zohar Peled May 19 '19 at 13:59
1

For the record: interfaces don't define fields at all, regardless of public/private/protected, so your expectation is simply not possible.

I've also considered using a property, but that seems unreasonable, as I don't want any extra functionality.

The issue isn't in the distinction between a field and a property, but rather because you're trying to use an interface to define a private.

Interfaces only define public properties (and methods), because interfaces effectively define the public inferface that is known to an external caller.

When I say public class Foo : IFoo, I am saying that external callers can observe an object of the Foo class as if it were an IFoo (they don't actually need to know it's a Foo or a DifferentFoo). This inherently forces me to then ensure that Foo fulfills the necessary IFoo contract.

In short, I want all of my objects that implement an interface to have a common field.

It makes no sense for interfaces to define private (or protected) fields because an external caller would not have access to them anyway.
Furthermore, since it's a private field, this would only be usable inside of the class itself. There is no way to define/reference this field in any other class (including the interface definition or any other implementation of the interface).

You call them a "common" field, but how would they every be common? No one would be able to use them, other than the class whose field it is. No one (not even the interface implementations themselves) will ever have access to more than one of these fields, there is no possible commonality (or benefit from it).


If the language were to accommodate what you want, there would be absolutely no functional benefit to it whatsoever. None. If you (or anyone else) can list any functional benefit, I'm interested in hearing it.

The only arguable benefit is that you could copy/paste code from one class to the next, because you would be able to guarantee that the referenced field (in the pasted code) has the same name.
But if you're copy/pasting, you're doing something wrong. Every time you copy/paste code, you should evaluate if you're not trying to work around a necessary abstraction. And in most cases, that is exactly what you're doing, which is bad practice.


If this is simply a matter of not wanting to type the same field declaration over and over, and you've already established that you're not trying to sweep a necessary abstraction under the rug, you can look into code generation tools that can generate the initial class definition for you.

However, if this is only for a handful of fields in a handful of classes, the effort is not worth the gains. You'll spend more time setting up the generation rules than you will copy/pasting the field declarations.

Flater
  • 12,908
  • 4
  • 39
  • 62
0

https://csharp.2000things.com/2011/10/28/443-an-interface-cannot-contain-fields/

Unfortunately interfaces cannot contain fields so your next best move would to define an abstract class with abstract methods and declare your fields within that class.

That way, anything that inherits the class will have to define the inherited methods similar to an interface with the additional fields from the base class

James m
  • 144
  • 12
0

If you want a field that is to be used only inside a base and all its derived classes, then declare it as protected in an abstract base class, as private would instead hide it to all the inheriting classes as well. If its value should be common for every class, you can still make it const or readonly and initialize it in the base class, so the derived classes cannot modify it (refer to this question to choose between the two modifiers).
As others have already explained, interfaces only allow public properties to be declared. Either you accept that, or you use an abstract class.

EDIT: Based on the new information provided by the OP, I suggest the use of a property in the base interface. That's the closest you can get to a commonly-shared public field without using an asbtract class.

StackLloyd
  • 409
  • 2
  • 9