هواشناسی

هواشناسی

تمرین یادگیری

مقدمه

Stringer یک اینترفیس برای تعیین قالب رشته‌ای مقادیر است.

این اینترفیس از یک متد واحد به اسم String تشکیل شده است:

type Stringer interface {
    String() string
}

نوع‌هایی که می‌خواهند این اینترفیس را پیاده‌سازی کنند باید متدی به اسم String() داشته باشند که یک نمایش رشته‌ای خوانا برای انسان از آن نوع را برمی‌گرداند. بسته‌ی fmt (و بسیاری از بسته‌های دیگر) برای قالب‌بندی و چاپ مقادیر به دنبال همین متد می‌گردد.

مثال: فاصله‌ها

فرض کنید روی برنامه‌ای کار می‌کنیم که با فاصله‌های جغرافیایی اندازه‌گیری‌شده در واحدهای مختلف سروکار دارد. نوع‌های DistanceUnit و Distance را به شکل زیر تعریف کرده‌ایم:

type DistanceUnit int

const (
	Kilometer    DistanceUnit = 0
	Mile         DistanceUnit = 1
)

type Distance struct {
	number float64
	unit   DistanceUnit
}

در مثال بالا، Kilometer و Mile ثابت‌هایی از نوع DistanceUnit هستند.

این نوع‌ها اینترفیس Stringer را پیاده‌سازی نمی‌کنند، چون متد String را ندارند. در نتیجه، توابع fmt مقادیر Distance را با «قالب پیش‌فرض» Go چاپ می‌کنند:

mileUnit := Mile
fmt.Sprint(mileUnit)
// => 1
// The result is '1' because that is the underlying value of the 'Mile' constant (see constant declarations above)

dist := Distance{number: 790.7, unit: Kilometer}
fmt.Sprint(dist)
// => {790.7 0}
// not a very useful output!

برای اینکه خروجی اطلاعات بیشتری بدهد، اینترفیس Stringer را برای نوع‌های DistanceUnit و Distance پیاده‌سازی می‌کنیم و به هر نوع یک متد String اضافه می‌کنیم:

func (sc DistanceUnit) String() string {
	units := []string{"km", "mi"}
	return units[sc]
}

func (d Distance) String() string {
	return fmt.Sprintf("%v %v", d.number, d.unit)
}

توابع بسته‌ی fmt هنگام قالب‌بندی مقادیر Distance این متدها را فراخوانی می‌کنند:

kmUnit := Kilometer
kmUnit.String()
// => km

mileUnit := Mile
mileUnit.String()
// => mi

dist := Distance{
	number: 790.7,
	unit: Kilometer,
}
dist.String()
// => 790.7 km

دستورالعمل‌ها

تیم شما روی یک برنامه‌ی هواشناسی کار می‌کند. آن‌ها یک API تعریف کرده‌اند که انواع و ثابت‌های گوناگونی برای نمایش داده‌های هواشناسی دارد؛ فایل meteorology.go را ببینید.

وظیفه‌ی شما این است که متدهای String مناسب را به همه‌ی انواع اضافه کنید تا «رابط» Stringer را پیاده‌سازی کنند.

1. پیاده‌سازی رابط Stringer برای نوع TemperatureUnit

بعد از کمی بحث، تیم توافق کرده است که یکای دما یا Celsius خواهد بود یا Fahrenheit. مقادیر باید همان‌طور که در مثال‌های زیر نشان داده شده قالب‌بندی شوند.

نوع TemperatureUnit را طوری تغییر دهید که با افزودن یک متد String به آن، رابط Stringer را پیاده‌سازی کند. این متد باید رشته‌ی "°C" را برگرداند اگر یکای دما سلسیوس است، و "°F" را اگر یکای دما فارنهایت است.

celsiusUnit := Celsius
fahrenheitUnit := Fahrenheit

celsiusUnit.String()
// => °C
fahrenheitUnit.String()
// => °F
fmt.Sprint(celsiusUnit)
// Output: °C

2. پیاده‌سازی رابط Stringer برای نوع Temperature

مقادیر دما از یک عدد صحیح و یک یکای دما تشکیل شده‌اند. باید همانند مثال‌های زیر قالب‌بندی شوند.

برای این کار، نوع Temperature را طوری تغییر دهید که با افزودن یک متد String به آن، رابط Stringer را پیاده‌سازی کند. این متد باید رشته‌ای برگرداند که مقدار عددی دما و یکای دما در آن با یک فاصله از هم جدا شده‌اند: <temperature> <unit>:

celsiusTemp := Temperature{
    degree: 21,
    unit: Celsius,
}
celsiusTemp.String()
// => 21 °C
fmt.Sprint(celsiusTemp)
// Output: 21 °C

fahrenheitTemp := Temperature{
    degree: 75,
    unit: Fahrenheit,
}
fahrenheitTemp.String()
// => 75 °F
fmt.Sprint(fahrenheitTemp)
// Output: 75 °F

3. پیاده‌سازی رابط Stringer برای نوع SpeedUnit

بعد از بحث‌های طولانی، تیم توافق کرده است که یکای سرعت باد یا KmPerHour خواهد بود یا MilesPerHour. مقادیر باید همانند مثال‌های زیر قالب‌بندی شوند.

برای این کار، نوع SpeedUnit را طوری تغییر دهید که با افزودن یک متد String به آن، رابط Stringer را پیاده‌سازی کند. این متد باید رشته‌ی "km/h" را برگرداند اگر یکای سرعت کیلومتر بر ساعت است، و "mph" را اگر یکای سرعت مایل بر ساعت است:

mphUnit := MilesPerHour
mphUnit.String()
// => mph
fmt.Sprint(mphUnit)
// Output: mph

kmhUnit := KmPerHour
kmhUnit.String()
// => km/h
fmt.Sprint(kmhUnit)
// Output: km/h

4. پیاده‌سازی رابط Stringer برای Speed

مقادیر سرعت باد از یک عدد صحیح و یک یکای سرعت تشکیل شده‌اند. باید همانند مثال زیر قالب‌بندی شوند.

برای این کار، نوع Speed را طوری تغییر دهید که با افزودن یک متد String به آن، رابط Stringer را پیاده‌سازی کند. این متد باید رشته‌ای برگرداند که مقدار عددی سرعت و یکای سرعت در آن با یک فاصله از هم جدا شده‌اند: <speed> <unit>:

windSpeedNow := Speed{
    magnitude: 18,
    unit: KmPerHour,
}
windSpeedNow.String()
// => 18 km/h
fmt.Sprintf(windSpeedNow)
// Output: 18 km/h

windSpeedYesterday := Speed{
    magnitude: 22,
    unit: MilesPerHour,
}
windSpeedYesterday.String()
// => 22 mph
fmt.Sprint(windSpeedYesterday)
// Output: 22 mph

5. پیاده‌سازی رابط Stringer برای نوع MeteorologyData

داده‌های هواشناسی مکان، دما، جهت باد، سرعت باد و رطوبت را مشخص می‌کند. باید همانند مثال زیر قالب‌بندی شود:

برای این کار، نوع MeteorologyData را طوری تغییر دهید که با افزودن یک متد String به آن، رابط Stringer را پیاده‌سازی کند. این متد باید داده‌های هواشناسی را در قالب زیر برگرداند:

<location>: <temperature>, Wind <wind_direction> at <wind_speed>, <humidity>% Humidity
sfData := MeteorologyData{
    location: "San Francisco",
    temperature: Temperature{
        degree: 57,
        unit: Fahrenheit
    },
    windDirection: "NW",
    windSpeed: Speed{
        magnitude: 19,
        unit: MilesPerHour
    },
    humidity: 60
}

sfData.String()
// => San Francisco: 57 °F, Wind NW at 19 mph, 60% Humidity
fmt.Sprint(sfData)
// Output: San Francisco: 57 °F, Wind NW at 19 mph, 60% Humidity
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Go Exercism

آماده‌اید هواشناسی را شروع کنید؟

در Exercism ثبت‌نام کنید تا Go را همراه با 34 مفهوم166 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.