-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Text, images, code for inheritance tutorial #1316
Conversation
❌ Validation status: errors
docs/csharp/tutorials/inheritance.md
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
✅ Validation status: passed
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
❌ Validation status: errors
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ron, This looks really good. Like the LINQ tutorial Steve did, we should upgrade the code samples to use the modern language features.
One concept that needs to be explained better is the distinction between inheritance and visibility. Other than constructors, every member is inherited (except instance constructors, static constructors and finalizers). However, whether those members are visible depends on the member's access modifier.
|
||
> [!NOTE] | ||
> Structs do not support inheritance, but they can implement interfaces. For more information, see [Interfaces](../../../csharp/programming-guide/interfaces/index.md). | ||
|
||
Conceptually, a derived class is a specialization of the base class. For example, if you have a base class `Animal`, you might have one derived class that is named `Mammal` and another derived class that is named `Reptile`. A `Mammal` is an `Animal`, and a `Reptile` is an `Animal`, but each derived class represents different specializations of the base class. | ||
|
||
When you define a class to derive from another class, the derived class implicitly gains all the members of the base class, except for its constructors and destructors. The derived class can thereby reuse the code in the base class without having to re-implement it. In the derived class, you can add more members. In this manner, the derived class extends the functionality of the base class. | ||
When you define a class to derive from another class, the derived class implicitly gains all the members of the base class, except for its constructors and destructors, private members, and static members. The derived class can thereby reuse the code in the base class without having to re-implement it. In the derived class, you can add more members. In this manner, the derived class extends the functionality of the base class. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Static members are inherited:
public class B
{
public static void DeclaredInB()
{
Console.WriteLine("Declared in Base");
}
}
public class D :B
{
}
class Program
{
static void Main(string[] args)
{
D.DeclaredInB();
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BillWagner. I can't believe that I missed that. I've corrected it.
|
||
The following illustration shows a class `WorkItem` that represents an item of work in some business process. Like all classes, it derives from <xref:System.Object?displayProperty=fullName> and inherits all its methods. `WorkItem` adds five members of its own. These include a constructor, because constructors are not inherited. Class `ChangeRequest` inherits from `WorkItem` and represents a particular kind of work item. `ChangeRequest` adds two more members to the members that it inherits from `WorkItem` and from <xref:System.Object>. It must add its own constructor, and it also adds `originalItemID`. Property `originalItemID` enables the `ChangeRequest` instance to be associated with the original `WorkItem` to which the change request applies. | ||
The following illustration shows a class `WorkItem` that represents an item of work in some business process. Like all classes, it derives from <xref:System.Object?displayProperty=fullName> and inherits all its instance methods. `WorkItem` adds five members of its own. These include a constructor, because constructors are not inherited. Class `ChangeRequest` inherits from `WorkItem` and represents a particular kind of work item. `ChangeRequest` adds two more members to the members that it inherits from `WorkItem` and from <xref:System.Object>. It must add its own constructor, and it also adds `originalItemID`. Property `originalItemID` enables the `ChangeRequest` instance to be associated with the original `WorkItem` to which the change request applies. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove 'instance'. See previous comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BillWagner I've modified this discussion extensively to discuss visibility (which addressed your general comment) and added an example. Thanks -- I think this makes it much less confusing.
|
||
- [Destructors](../programming-guide/classes-and-structs/destructors.md), which are called by the runtime's garbage collector to destroy instances of a class. | ||
|
||
- [Static members](../programming-guide/classes-and-structs/static-classes-and-static-class-members.md). Only instance members are inherited by base classes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be deleted. Static members are inherited.
|
||
- [Static members](../programming-guide/classes-and-structs/static-classes-and-static-class-members.md). Only instance members are inherited by base classes. | ||
|
||
- [Private](../language-reference/keywords/private.md) and [internal](../language-reference/keywords/internal.md) members. However, internal members of a base class may be *visible* to a derived class if the two types are in the same assembly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internal members are inherited. Their visibility is limited to the assembly where the base class is declared, but they are inherited.
} | ||
``` | ||
|
||
In some cases, a derived class *must* override the base class implementation. Base class members marked with the [abstract](../language-reference/keywords/abstract.md) keyword require that derived classes override them. Attempting to compile the following example generates compiler error CS0534, "<class> does not implement inherited abstract member <member>', because class `B` provides no implementtion for `A.Method1`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: implementtion
authorName = author; | ||
} | ||
|
||
public string ISBN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auto implemented (possibly readonly) properties here....
|
||
public class Automobile | ||
{ | ||
public string _make; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be private fields. (And I think using auto-implemented properties would be best).
|
||
public abstract double Perimeter { get; } | ||
|
||
public override string ToString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These one line methods could all be expression bodied members.
this.length = length; | ||
} | ||
|
||
public double Side |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer either read only auto implemented properties, or expression bodied members (for Area and Perimeter)
private PublicationType pubType; | ||
private string copyrName; | ||
private int copyrDate; | ||
private int totalPages; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer auto implemented properties, readonly where that matches the design
@BillWagner Thanks for all of the comments and reviewing the code so carefully. I've made all of your suggested changes, as well as added interpolated strings, so I think that the code is much more "modern". |
❌ Validation status: errors
docs/csharp/tutorials/inheritance.md
For more details, please refer to the build report. Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report. |
|
||
- [Destructors](../programming-guide/classes-and-structs/destructors.md), which are called by the runtime's garbage collector to destroy instances of a class. | ||
|
||
- [Private](../language-reference/keywords/private.md) and [internal](../language-reference/keywords/internal.md) members. However, internal members of a base class may be *visible* to a derived class if the two types are in the same assembly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This paragraph should e removed, after the changes you've made.
@rpetrusha I read this again this morning. It looks great. There's one typo left, and one paragraph that still states that private and internal methods aren't inherited. Once those two are fixed, LGTM. |
Text, images, code for inheritance tutorial
Summary
A tutorial on inheritance that addresses basic concepts, implicit inheritance, inheritance for code reuse, and abstract base classes.
Fixes #265
Suggested Reviewers
@BillWagner @mairaw @stevehoag