Skip to content
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

Merged
merged 7 commits into from
Dec 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ translation.priority.ht:
- "zh-tw"
---
# Inheritance (C# Programming Guide)
Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics (or *pillars*) of object-oriented programming. Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. The class whose members are inherited is called the *base class*, and the class that inherits those members is called the *derived class*. A derived class can have only one direct base class. However, inheritance is transitive. If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics of object-oriented programming. Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. The class whose members are inherited is called the *base class*, and the class that inherits those members is called the *derived class*. A derived class can have only one direct base class. However, inheritance is transitive. If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.

> [!NOTE]
> Structs do not support inheritance, but they can implement interfaces. For more information, see [Interfaces](../../../csharp/programming-guide/interfaces/index.md).
Expand Down Expand Up @@ -68,9 +69,6 @@ Class inheritance

Interfaces are used to define specific capabilities for classes that do not necessarily have an "is a" relationship. For example, the <xref:System.IEquatable%601?displayProperty=fullName> interface can be implemented by any class or struct that has to enable client code to determine whether two objects of the type are equivalent (however the type defines equivalence). <xref:System.IEquatable%601> does not imply the same kind of "is a" relationship that exists between a base class and a derived class (for example, a `Mammal` is an `Animal`). For more information, see [Interfaces](../../../csharp/programming-guide/interfaces/index.md).

## Derived Class Access to Base Class Members
A derived class has access to the public, protected, internal, and protected internal members of a base class. Even though a derived class inherits the private members of a base class, it cannot access those members. However, all those private members are still present in the derived class and can do the same work they would do in the base class itself. For example, suppose that a protected base class method accesses a private field. That field has to be present in the derived class for the inherited base class method to work correctly.

## Preventing Further Derivation
A class can prevent other classes from inheriting from it, or from any of its members, by declaring itself or the member as [sealed](../../../csharp/language-reference/keywords/sealed.md). For more information, see [Abstract and Sealed Classes and Class Members](../../../csharp/programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members.md).

Expand Down
3 changes: 3 additions & 0 deletions docs/csharp/tutorials/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ The following tutorials enable you to build C# programs using [CoreCLR](https://
the basics of the Task based asynchronous programming model.
* [REST Client](console-webapiclient.md): demonstrates web communications, JSON serialization, and Object Oriented
features in the C# language.

* [Inheritance in C# and .NET](inheritance.md): demonstrates inheritance in C#, including the use of inheritance to define base classes, abstract base classes, and derived classes.

* [Working with LINQ](working-with-linq.md): demonstrates many of the features of LINQ and the language elements that support it.

* [Microservices hosted in Docker](microservices.md): demonstrates building an ASP.NET Core microservice and hosting it in Docker.
301 changes: 301 additions & 0 deletions docs/csharp/tutorials/inheritance.md

Large diffs are not rendered by default.

Binary file added docs/csharp/tutorials/media/book-class.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/csharp/tutorials/media/publication-class.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
161 changes: 161 additions & 0 deletions samples/snippets/csharp/tutorials/inheritance/base-and-derived.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@

// <Snippet1>
using System;

public enum PublicationType { Misc, Book, Magazine, Article };

public abstract class Publication
{
private bool published = false;
private DateTime datePublished;
private int totalPages;

public Publication(string title, string publisher, PublicationType type)
{
if (publisher == null)
throw new ArgumentNullException("The publisher cannot be null.");
else if (String.IsNullOrWhiteSpace(publisher))
throw new ArgumentException("The publisher cannot consist only of whitespace.");
Publisher = publisher;

if (title == null)
throw new ArgumentNullException("The title cannot be null.");
else if (String.IsNullOrWhiteSpace(title))
throw new ArgumentException("The title cannot consist only of whitespace.");
Title = title;

Type = type;
}

public string Publisher { get; }

public string Title { get; }

public PublicationType Type { get; }

public string CopyrightName { get; private set; }

public int CopyrightDate
{ get; private set; }

public int Pages
{ get { return totalPages; }
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException("The number of pages cannot be zero or negative.");
totalPages = value;
}
}

public string GetPublicationDate()
{
if (!published)
return "NYP";
else
return datePublished.ToString("d");
}

public void Publish(DateTime datePublished)
{
published = true;
this.datePublished = datePublished;
}

public void Copyright(string copyrightName, int copyrightDate)
{
if (copyrightName == null)
throw new ArgumentNullException("The name of the copyright holder cannot be null.");
else if (String.IsNullOrWhiteSpace(copyrightName))
throw new ArgumentException("The name of the copyright holder cannot consist only of whitespace.");
CopyrightName = copyrightName;

int currentYear = DateTime.Now.Year;
if (copyrightDate < currentYear - 10 || copyrightDate > currentYear + 2)
throw new ArgumentOutOfRangeException($"The copyright year must be between {currentYear -10} and {currentYear + 1}");
CopyrightDate = copyrightDate;
}

public override string ToString() => Title;
}
// </Snippet1>

namespace DerivedClasses
{
// <Snippet2>
using System;

public sealed class Book : Publication
{
public Book(string title, string author, string publisher) :
this(title, String.Empty, author, publisher)
{ }

public Book(string title, string isbn, string author, string publisher) : base(title, publisher, PublicationType.Book)
{
// isbn argument must be a 10- or 13-character numeric string without "-" characters.
// We could also determine whether the ISBN is valid by comparing its checksum digit
// with a computed checksum.
//
if (! String.IsNullOrEmpty(isbn)) {
// Determine if ISBN length is correct.
if (! (isbn.Length == 10 | isbn.Length == 13))
throw new ArgumentException("The ISBN must be a 10- or 13-character numeric string.");
ulong nISBN = 0;
if (! UInt64.TryParse(isbn, out nISBN))
throw new ArgumentException("The ISBN can consist of numeric characters only.");
}
ISBN = isbn;

Author = author;
}

public string ISBN { get; }

public string Author { get; }

public Decimal Price { get; private set; }

// A three-digit ISO currency symbol.
public string Currency { get; private set; }


// Returns the old price, and sets a new price.
public Decimal SetPrice(Decimal price, string currency)
{
if (price < 0)
throw new ArgumentOutOfRangeException("The price cannot be negative.");
Decimal oldValue = Price;
Price = price;

if (currency.Length != 3)
throw new ArgumentException("The ISO currency symbol is a 3-character string.");
Currency = currency;

return oldValue;
}

public override bool Equals(object obj)
{
Book book = obj as Book;
if (book == null)
return false;
else
return ISBN == book.ISBN;
}

public override int GetHashCode() => ISBN.GetHashCode();

public override string ToString() => $"{(String.IsNullOrEmpty(Author) ? "" : Author + ", ")}{Title}";
}
// </Snippet2>
}

public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}

25 changes: 25 additions & 0 deletions samples/snippets/csharp/tutorials/inheritance/basics.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;

// <Snippet1>
public class A
{
public void Method1()
{
// Method implementation.
}
}

public class B : A
{ }


public class Example
{
public static void Main()
{
B b = new B();
b.Method1();
}
}
// </Snippet1>

51 changes: 51 additions & 0 deletions samples/snippets/csharp/tutorials/inheritance/is-a.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// <Snippet1>
using System;

public class Automobile
{
public Automobile(string make, string model, int year)
{
if (make == null)
throw new ArgumentNullException("The make cannot be null.");
else if (String.IsNullOrWhiteSpace(make))
throw new ArgumentException("make cannot be an empty string or have space characters only.");
Make = make;

if (model == null)
throw new ArgumentNullException("The model cannot be null.");
else if (String.IsNullOrWhiteSpace(make))
throw new ArgumentException("model cannot be an empty string or have space characters only.");
Model = model;

if (year < 1857 || year > DateTime.Now.Year + 2)
throw new ArgumentException("The year is out of range.");
Year = year;
}

public string Make { get; }

public string Model { get; }

public int Year { get; }

public override string ToString() => $"{Year} {Make} {Model}";
}
// </Snippet1>

namespace IsA_Namespace
{
// <Snippet2>
using System;

public class Example
{
public static void Main()
{
var packard = new Automobile("Packard", "Custom Eight", 1948);
Console.WriteLine(packard);
}
}
// The example displays the following output:
// 1948 Packard Custom Eight
// </Snippet2>
}
35 changes: 35 additions & 0 deletions samples/snippets/csharp/tutorials/inheritance/private.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// <Snippet1>
using System;

public class A
{
private int value = 10;

public class B : A
{
public int GetValue()
{
return this.value;
}
}
}

public class C : A
{
// public int GetValue()
// {
// return this.value;
// }
}

public class Example
{
public static void Main(string[] args)
{
var b = new A.B();
Console.WriteLine(b.GetValue());
}
}
// The example displays the following output:
// 10
// </Snippet1>
Loading