Enter a dial for some - but not all - of the inherited classes

It's hard for me to implement a property in C # that only has a getter in an abstract base class, but where do I need to enter setter in one of the derived classes.


Update: for a shorter explanation of a generic example of this question, see this question . The selected answer explained why it is currently not possible to do this in C #, however, in my opinion, a satisfactory solution has not yet been provided.


An overview of my class diagram is shown below:

Class diagram

My goal is that the two TextElementStatic and TextElementReferenceSource classes should have the Text property with both getters and setters, and the TextElementReferenceTarget class should have the Text property with a getter only. I constantly use ITextElement , referring to all these objects, and I need to make sure that there is only a recipient in the ITextElement interface. In addition, the TextElement base class implements a lot of common code, so all classes must inherit from this class.

My current code is as follows:

Interface: ITextElement

public interface ITextElement { string Text { get; } } 

Interface: ITextElementUpdatable

 public interface ITextElementUpdatable : ITextElement { new string Text { get; set; } } 

Abstract class: TextElement (Here my problem is explained below)

 public abstract class TextElement : ITextElement { // I want to mark this 'abstract', but that causes my problem public virtual string Text { get { // NOTE: This should never be called Debug.Fail("Called virtual Text getter that should never be called"); return default(string); } } } 

Abstract class: TextElementUpdatable

 public abstract class TextElementUpdatable : TextElement, ITextElementUpdatable { // Should have both a getter and a setter public new virtual string Text { get; set; } } 

Class: TextElementStatic

 public class TextElementStatic : TextElementUpdatable { // Should have both a getter and a setter // No Text property declaration // Inherits Text property from TextElementUpdatable } 

Class: TextElementReferenceSource

 public class TextElementReferenceSource : TextElementUpdatable { // Should have both a getter and a setter public override string Text { get { return _internalobject.Text; } set { _internalobject.Text = value; } } } 

Class: TextElementReferenceTarget

 public class TextElementReferenceTarget : TextElement { // Should ONLY have a getter public override string Text { get { return _internalobject.Text; } } } 

So my problem is: I really want to declare the Text property in the abstract abstract TextElement of the base class, because it should always be implemented in derived classes (both TextElementUpdatable, TextElementReferenceSource, and TextElementReferenceTarget implements this property). However, if I try to convert the property to public abstract string Text { get; } public abstract string Text { get; } , I get an error in TextElementUpdatable , indicating that

 TextElementUpdatable.Text hides the inherited property TextElement.Text 

Also, if I change the property in TextElementUpdatable from new to override , the error message is replaced with:

 Cannot override because TextElement.Text does not have an overridable set accessor 

Now I can go back to TextElement and change the property to public virtual string Text { get; private set; } public virtual string Text { get; private set; } public virtual string Text { get; private set; } and call it day, since this method should never be called in any case (which is basically the solution that I have now), However, if I or someone later create another derived class, I want to force me / they implement the Text property, so I would rather mark it abstract than providing a virtual implementation.

Any suggestions on how I can do this right, even if it requires a lot of refactoring?

I know that I can distinguish two goals for it by providing one inherited Text property using getter only, and then introduce the SetText() method in the ITextElementUpdatable interface. However, I am wondering if a good solution can only be found with properties.


Another similar question, but without any answers, I was able to use: C # - what should I do when each inherited class needs a getter from the base class, and setter is for the ONE inherited class only

+6
source share
2 answers

This is a really exciting issue, but ... You should use a new keyword, which is not good practice. Try to avoid them. Of course, the property names can be the same in the interfaces, but if both are implemented by the class (and one of the attributes defined without a setter), we must implement them explicitly. We must recognize that these properties are "conflicting." You can introduce abstract methods:

 public abstract class TextElement : ITextElement { public string Text { get { return GetText(); } } protected abstract string GetText(); } public abstract class TextElementUpdatable : TextElement, ITextElementUpdatable { string ITextElementUpdatable.Text { get { return GetText(); } set { SetText(value); } } protected abstract void SetText(string text); } 
+1
source

It can be a little confusing that you use the same property in your hierarchy with different values. Perhaps the implementation of ITextElement.get_Text and ITextElementUpdatable.get_Text will diverge later - the interfaces define two independent behaviors, and we do not use basic types all the time, for example string. Therefore, I suggest that you have a property in ITextElement for read-only purpose and another property in ITextElementUpdatable with a different name. That way your methods can be defined as abstract, of course.

0
source

Source: https://habr.com/ru/post/969766/


All Articles