Distracted or abstracted

Thanks in advance for this. I don’t quite understand how and when to use theses, so I try to think about it in every project I’m working on to see if it will ever be clicked;) |

Also, the combination of accessibility levels (private, protected, internal) with the keywords static, abstract, and override tends to leave me confused. How to define this method / property / class ....

This is not all a big mystery for me, but some projects encode me in circles when they deal with these topics.

With that said

I have an application that reads an XML document and outputs text and image files. Im also saves all the information in the database. It works for me well.

XML has a standard implementation with required fields and is used by several organizations to send data to my application. All organizations should use (at least) the necessary nodes / elements that are described in the XML Implementation Guide.

So, I want to have a default data object type in order to be able to output a specific organization data type for the required elements. (If this object will be used, these are the fields that must be implemented).

If org. just uses the default requirements, I can use the default object. If they use additional (optional) fields, I must create a new type that inherits the default type.

My first thought was to use an abstract class that had protected properties for my minimum requirements:

public abstract partial class AbstractDataObject { protected string DataObjectName; protected DateTime? DataObjectDate; etc... } 

Then, if the organization just uses the required node elements and optional elements, I can use the default object.

 internal partial class DefaultDataObject : AbstractDataObject { public new string DataObjectName { get; set; } public new DateTime? DataObjectDate { get; set; } etc... } 

But if the organization uses the optional fields of the required node, I can use the derived data object of the organization.

 internal sealed partial class OranizationDataObject : AbstractDataObject { public new string DataObjectName { get; set; } public new DateTime? DataObjectDate { get; set; } etc... //Optional fields used by this organization public string DataObjectCode { get; set; } etc... } 

Do I need an abstract class? It seems to me that I can just create a DefaultDataObject (something like):

 internal partial class DefaultDataObject { public virtual string DataObjectName { get; set; } public virtual DateTime? DataObjectDate { get; set; } etc... } 

And then:

 internal sealed partial class OranizationDataObject : DefaultDataObject { public override string DataObjectName { get; set; } public override DateTime? DataObjectDate { get; set; } etc... //Optional fields used by this organization public string DataObjectCode { get; set; } etc... } 

I'm just trying to figure out how to define these objects so that I can reuse them for each organization. Both methods seem to work, but I hope to understand how to determine them correctly.

Getting XML into the above objects:

 public DefaultDataObject ExtractXmlData(XContainer root) { var myObject = (from t in root. Elements("ElementA").Elements("ElementB") select new DefaultDataObject() { DataObjectName = (String)t.Element("ChildElement1"), DataObjectDate = Program.TryParseDateTime((String) t.Elements("ChildElement2") .ElementAtOrDefault(0) ), etc.... 

OR

 public OranizationDataObject ExtractXmlData(XContainer root) { var myObject = (from t in root. Elements("ElementA").Elements("ElementB") select new OranizationDataObject() { DataObjectName = (String)t.Element("ChildElement1"), DataObjectDate = Program.TryParseDateTime( (String)t.Elements("ChildElement2") .ElementAtOrDefault(0)), DataObjectCode = (String)t.Element("ChildElement3"), 

etc....

Thanks again for reading. Remember to consult your waiting staff.

Joe

+4
source share
4 answers
  • First of all, your base class should not be abstract if it is a simple DTO class. If you don't have functionality that needs to be implemented differently in derived classes, you can simply make it a simple base class that will contain common properties .

  • Further, it makes no sense to declare properties in the base class (annotation in your case) if you are going to hide (using the new keyword). The first piece of code, DefaultDataObject unnecessarily creates a bunch of new properties with the same name. Delete them completely - they are already defined in the base class.

    [Edit] I did not notice this initially, and @svick warned me that your base class actually contains fields instead of properties, which makes me wonder why you needed to add the new keyword. I quickly looked through your code and saw them as properties. In any case, you should never open public fields - at least change them for automatically implemented properties by adding the { get; set; } { get; set; } { get; set; } .

    In other words, this will just work:

     // this doesn't need to be abstract. // just put all the common stuff inside. public class BaseDO { // as svick pointed out, these should also be properties. // you should *never* expose public fields in your classes. public string Name { get; set; } public DateTime? Date { get; set; } } // don't use the new keyword to hide stuff. // in most cases, you won't need that behavior public class DerivedDO : BaseDO { // no need to repeat those properties from above, // only add **different ones** public string Code { get; set; } } 
  • As a side note, but still important IMHO, you should simplify the naming (and make it clearer what your code does). For example, there is no need to repeat "DataObject" in each property name. But since your code is probably just a simplified version, it doesn't matter.

  • Finally, have you heard of the XmlSerializer ? You do not need to manually move the XML elements. Just call XmlSerializer to serialize and deserialize the data.

+4
source

Everything I Need to Know, I Learned on Sesame Street
Scrub your class design is hard to make sure that you define everything that is the same and different. Play on the computer, so to speak, with your classes and see how they do the same, different or the same thing, but in different ways.

What is the same, different, one and the same, but in different ways, most likely, will change when playing on a computer.

Think about the general principles of the two pillars of OO classes. Polymorphism and Inheritance
How do you do it. Not so much in terms of implementing C # as such.

How things come together in the same versus different will contribute to the implementation
And all this is relative.

  • More of the same default behavior? Perhaps a concrete base class instead of an abstract one.
  • More of the same, but in a different way? Perhaps the abstract class instead of the concrete base class.
  • The default is x? Perhaps the virtual method.
  • Everyone does the same thing, but there are no two identical ways? A delegate possible.

Implementation Suggestions

  • Make methods and fields protected by default. Private not inherited. Design changes remain flexible. If something just needs to be private, fine.

  • virtual means you can change the implementation in a subclass. This does not mean that you should.

  • It seems like people are not using delegate s. They are super for polymorphic methods.

  • There is nothing wrong with public fields. What is the practical difference between a public field and a public automated property ? Nothing. They both directly return (or set) the base value. So, what's the point of even worrying about properties? If you want to publicly set the base value differently than this "natural" state. For example, returning a number in a specific format. And of course, you can have different properties for the same field.

  • A property can have get without set . Or vice versa. Also get and set can have different access levels. Often you will see this as open access and a protected (or closed) set.

+3
source

It depends on what the derived types will do. If they are going to use the default implementation and extend it somehow, then having a default class as a non-abstract base class would be great.

On the other hand, if they are likely to re-implement the functionality, you should have an abstract base class (or interface) and a separate default class.

If for some reason you do not know which one, you can let the heirs choose, having an abstract base class and leaving the class unsealed by default.

Also, looking at your code, it seems you misunderstood what the various keywords are doing. In most cases, you do not want to use new as follows. What he does is to identify another member with the same name that is not associated with the original. In addition, there is no reason for override if you do not want to change it. So, if you expect derived classes to not have to override properties, you don't need to make them virtual at all.

+2
source

An abstract class can already implement things that can be inherited

 public abstract class DataObjectBase { public string DataObjectName { get; set; } public DateTime? DataObjectDate { get; set; } } 

A particular class may add new properties and methods.

 public class DerivedDataObject : DataObjectBase { public int NewProperty { get; set; } } 

The DataObjectName and DataObjectDate already available in the new class, since they are automatically inherited from the base class.

If an abstract member is defined for an abstract class, however, you will have to implement it in a derived class.

Say the base class defines

 public abstract void SomeMethod(string name); 

The resulting class should do this.

 public override void SomeMethod(string name) { ... } 

If your base class does not have abstract elements, it should not be abstract and can directly play the role of your default data object.


The keyword "partial" is not required here. This is useful if you want to split a class one into several parts across several files.

The new keyword is incorrect here. It is used for a shadow inherited item. This means that the inherited member will be hidden β€œbehind” the new declaration. What you need is to override. This does not hide the member, but provides an alternative implementation of the same element in the derived class.

+1
source

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


All Articles