User98743 Ответов: 2

Основной вопрос о производном классе


Это мой первый производный класс, и я так запутался. Я не понимаю, как эти два класса общаются.

Я ожидаю, что мне придется инициализировать базовый класс, а затем инициализировать производный класс, потому что он выглядит так, как в Примере, который я рассматриваю.

Я надеялся создать производный класс, который наследует некоторые методы и поля от базового класса, который уже был инициализирован. Надеюсь, я выразился ясно, но если нет, пожалуйста, простите мое разочарование и позвольте мне уточнить.

Мой Базовый Класс:

using System;

namespace RickRoll
{
	public class DbDataSource
	{
		public string FilePath { get; }
		public string Server { get; }
		public string DataSource { get; }
		
		public DataFileType FileType { get; }
		public bool DataSourceIsFile { get; }


		/// <summary>
		/// The data source will be set to fhe file path unless server is null
		/// </summary>
		/// <param name="dbfilepath"></param>
		/// <param name="dbserver"></param>
		public DbDataSource(string dbfilepath, string dbserver)
		{
			FilePath = dbfilepath;
			Server = dbserver;
			FileType = GetDbFileType (dbfilepath);
			DataSource = dbserver ?? FilePath;                          // Set DataSource = Server.  If Server is null, set DataSource = file path
			DataSourceIsFile = (DataSource == dbfilepath);			// If DataSource = file path, DataSourceIsFile = true
		}

		/// <summary>
		/// DataFileType by File Extension
		/// </summary>
		/// <param name="path"></param>
		/// <returns></returns>
		private DataFileType GetDbFileType(string path)
		{
			DataFileType ft;
			string ext;
			if (path.Contains ("."))
			{
				string fpath = path.Replace ("|DataDirectory|" , AppDomain.CurrentDomain.BaseDirectory);
				ext = System.IO.Path.GetExtension (fpath).Replace ("." , "").ToUpper ( );
				ft = (DataFileType) Enum.Parse (typeof (DataFileType) , ext);           /// throw exception if extention is not in DataFileType enum or is null
			}
			else
			{
				ft = (DataFileType) Enum.Parse (typeof (DataFileType) , path.ToUpper ( ));           /// throw exception if extention is not in DataFileType enum or is null
			}
			return ft;
		}

		// <summary>
		/// Int enumeration of the supported file types
		/// </summary>
		public enum DataFileType
		{
			None,
			MDB = 1,       // 0 = not a configured data file
			ACCDB,
			MDF,           // Primary Data FIle
			NDF,           // File Group (secondary data files)
			XLS,           // Excel 97-2003 worksheet
			XLSX,          // Excel 2007 workbook
			XLSXM,         // Macro enabled workbook
			XLTM,          // Binary worksheet (BIFF12)
			XLW,           // Excel works space, previously known as workbook
			CSV,           // Comma separated values
			TAB,           // Tab separated values
			TSV,           // Tab separated values
			TXT            // Delimited Text file
		}

	}
}

Мой производный класс:

using System;

namespace RickRoll
{
	public class DbPRovider : DbDataSource
	{
		public DataProvider Provider { get; set; }

		public DbPRovider()
		{
			Provider = GetDbProvider (DbDataSource.FilePath);
		}

		/// <summary>
		/// Int enumeration of suported data sources
		/// </summary>
		public enum DataProvider
		{
			None,
			Microsoft_ACE_OLEDB_12_0 = 1,          // Microsoft.ACE.OLEDB.12.0 - MS OLEDB DataProvider for MDB or ACCDB or EXCEL
			Microsoft_ACE_OLEDB,               // Microsoft.ACE.OLEDB VersionIndependentProgID
			Microsoft_Jet_OLEDB_4_0,           // MS Access - Does not work with ACCDB or any SQL Server version
			Microsoft_Jet_OLEDB,               // Version Independent ProgID
			SQLNCLI11,                         // SQL Server Native Client for OleDb
			SQLNCLI,                           // Version Independent ProgID
			SQLOLEDB_1,                        // SQL Server OleDb - Does not work with SQL Server Express
			SQLOLEDB,                          // VersionIndependentProgID
			SQL__Server__Native__Client__11_0, // SQL Server Native Client using ODbC
			SQL__Server__Native__Client,       // Version Independent ProgID
			MSDASQL_1,                         // Microsoft OleDb Data Access Components using ODbC
			MSDASQL                            // Version Independent ProgID
		}



		private DataProvider GetDbProvider(DataFileType ft)
		{
			switch (ft)
			{
				case DataFileType.MDB:
				case DataFileType.ACCDB:
					return DataProvider.Microsoft_ACE_OLEDB_12_0;
				case DataFileType.MDF:
					return DataProvider.SQLNCLI11;                 // SQLOLEDB_1 and SQLOLEDB did not work with SQL Server Express
				case DataFileType.NDF:
					return DataProvider.SQLNCLI11;
				case DataFileType.XLS:
				case DataFileType.XLSX:
				case DataFileType.CSV:
				case DataFileType.TAB:
				case DataFileType.TSV:
				case DataFileType.TXT:
					return DataProvider.Microsoft_ACE_OLEDB_12_0;
				default:
					throw new ArgumentException ($"* * * DataFileType is not a supported data file format.  Database DataProvider could not be determined.");
			}
		}


	}
}


Что я уже пробовал:

Здесь я получаю ошибки:

public DbPRovider()
		{
			Provider = GetDbProvider (DbDataSource.FilePath);
		}


Не существует аргумента, соответствующего требуемому формальному параметру dbfilepath.

Какой смысл выводить из класса, если вы должны назначить его членов? Я ничего не понимаю.

Очень неприятно.

johannesnestler

так что все решения хороши и правильны - но то, что вы здесь имеете, - это просто недопонимание того, как называются конструкторы. таким образом, конструктор базового класса должен вызываться с некоторыми параметрами по умолчанию конструктором производного класса. Таким образом, ваш конструктор базового класса будет запущен, а ваши поля инициализированы - так что ООП работает так, как вы ожидали - просто прочитайте о конструкторах еще раз на MSDN или в вашей любимой книге...

2 Ответов

Рейтинг:
2

BillWoodruff

What's the point of deriving from a class, if you have to assign its members?
Наследование в C#-это "копирование" или передача данных во время компиляции. структура.

Это не копирование какого-то объекта. пример класса, а также текущее значение полей и/или свойств экземпляра класса в другой экземпляр.

Если вы хотите, чтобы поля и/или свойства настаивать их текущее значение в производных классах: используйте статическую объявленную реализацию.

Если вы хотите, чтобы каждое создание нового экземпляра производного класса инициализировало определенные значения, вы можете сделать это в конструкторе класса в базовом классе. Вы можете определять константы, поля и т. д., и до тех пор, пока их значения присутствует во время компиляции, экземпляры производного класса будут совместно использовать эти значения.

"Точка" наследования заключается в том, что она является ключевым компонентом ООП и облегчает повторное использование кода, разделение проблем и моделирование отношений, иерархий и т. д.

Дайте мне знать, если это будет полезно.


[no name]

Спасибо, Билл! Я откусил больше, чем мог прожевать, пытаясь одновременно заняться интерфейсами, наследованием, абстрактными классами. Я никогда не кодировал интерфейс или унаследованный класс, и большое количество примеров, которые пытаются описать эту тему с помощью "класса А, класса В и класса с", заставляет мою голову кружиться.

If you want Fields and/or Properties to persist their current values in derived Classes: use static declared implementation.

Первоначально я использовал статические поля, но затем изменил их, потому что прочитал, что 1) Вы никогда не должны использовать статические поля из-за чего-то, связанного с многопоточными средами, и 2) статический элемент занимает одно место в памяти. Это заставило меня подумать, что изменение значения статического члена в моем классе также должно изменить его значение везде, где есть ссылка на статическое поле.

То, с чем я действительно борюсь, - это взять что-то, что работало и имело смысл для меня, и превратить это во что-то, что придерживается принципов ООП.

Я собираюсь просидеть над этим всю ночь и действительно попытаться понять все, что вы сказали. Я, вероятно, слишком расстроен, чтобы сделать это сегодня вечером. Большое вам спасибо!

BillWoodruff

Привет, Рик, не волнуйся, это займет некоторое время, чтобы переварить ООП в C#.

Я нахожу, что это помогает моим студентам думать о "чертежах", когда речь заходит о наследстве. Схема элементов определяет структуру.

Абстрактный класс может как указывать структуру, так и обеспечивать реализацию. Виртуальные Ckass-это совсем другая история.

Я использую аналогию "спецификации материалов" для описания интерфейсов: это не только спецификация структуры, но и контракт, который говорит, что класс, который его использует, должен реализовать/предоставить.

Статический объявленный класс, свойство, метод или поле становятся единственной реализацией, доступной для каждого экземпляра производного класса; да, могут быть проблемы (многопоточности) со статическими сущностями, но они широко полезны.

[no name]

Это исключительное описание. Я положила его на доску в своей спальне. Да, у меня в спальне есть доска. Их было трое. И классная доска. Эта штука очень жесткая.

Рейтинг:
0

Peter Vegter

Чтобы получить доступ к членам наследуемого класса, вы должны использовать ключевое слово 'base:

Provider = GetDbProvider(base.FilePath);
// or just the member name:
Provider = GetDbProvider(FilePath);

В вашем коде "DbDataSource" - это тип (класс), а не объект, который вы можете использовать так, как вы пытаетесь это сделать.
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/inheritance[^]