В дополнение к другим ответам, я рекомендую эту онлайн-службу open source jsonschema2pojo.org для быстрого генерации Java-классов из json или json-схемы для GSON, Jackson 1.x или Jackson 2.x. Например, если у вас есть:
{
"pageInfo": {
"pageName": "abc",
"pagePic": "http://example.com/content.jpg"
}
"posts": [
{
"post_id": "123456789012_123456789012",
"actor_id": 1234567890,
"picOfPersonWhoPosted": "http://example.com/photo.jpg",
"nameOfPersonWhoPosted": "Jane Doe",
"message": "Sounds cool. Can't wait to see it!",
"likesCount": 2,
"comments": [],
"timeOfPost": 1234567890
}
]
}
jsonschema2pojo.org для генерируемого GSON:
@Generated("org.jsonschema2pojo")
public class Container {
@SerializedName("pageInfo")
@Expose
public PageInfo pageInfo;
@SerializedName("posts")
@Expose
public List posts = new ArrayList();
}
@Generated("org.jsonschema2pojo")
public class PageInfo {
@SerializedName("pageName")
@Expose
public String pageName;
@SerializedName("pagePic")
@Expose
public String pagePic;
}
@Generated("org.jsonschema2pojo")
public class Post {
@SerializedName("post_id")
@Expose
public String postId;
@SerializedName("actor_id")
@Expose
public long actorId;
@SerializedName("picOfPersonWhoPosted")
@Expose
public String picOfPersonWhoPosted;
@SerializedName("nameOfPersonWhoPosted")
@Expose
public String nameOfPersonWhoPosted;
@SerializedName("message")
@Expose
public String message;
@SerializedName("likesCount")
@Expose
public long likesCount;
@SerializedName("comments")
@Expose
public List
Я бы не считал Shadows действительно концепцией ООП. Переопределения указывают, что вы предоставляете новые или дополнительные функции для метода / свойства и т. Д., Которые были объявлены в классе предков. Тени действительно обманывают компилятор, думая, что родительский метод / свойство и т. Д. Даже не существует.
Я не использую Shadows. Придерживайтесь переопределений. Эти типы полезных «особенностей», которые VB обеспечивал годами, в конечном итоге приводят к горю в какой-то момент.
Ну вот ответ по коду.
Module Module1
Sub Main()
Dim object1 As Parent = New Child()
Console.WriteLine("object1, reference type Parent and object type Child")
object1.TryMe1()
object1.TryMe2()
object1.TryMe3()
Console.WriteLine("")
Console.WriteLine("")
Console.WriteLine("object2, reference type Child and object type Child")
Dim object2 As Child = New Child()
object2.TryMe1()
object2.TryMe2()
object2.TryMe3()
Console.ReadLine()
End Sub
End Module
Public Class Parent
Public Sub TryMe1()
Console.WriteLine("Testing Shadow: Parent.WriteMe1")
End Sub
Public Overridable Sub TryMe2()
Console.WriteLine("Testing override: Parent.WriteMe2")
End Sub
Public Sub TryMe3()
Console.WriteLine("Testing Shadow without explicitly writing shadow modifier: Parent.WriteMe3")
End Sub
End Class
Public Class Child
Inherits Parent
Public Shadows Sub TryMe1()
Console.WriteLine("Testing Shadow: Child.WriteMe1")
End Sub
Public Overrides Sub TryMe2()
Console.WriteLine("Testing override: Child.WriteMe2")
End Sub
Public Sub TryMe3()
Console.WriteLine("Testing Shadow without explicitly writing shadow modifier: Child.WriteMe3")
End Sub
End Class
'Output:
'object1, reference type Parent and object type Child
'Testing Shadow: Parent.WriteMe1
'Testing override: Child.WriteMe2
'Testing Shadow without explicitly writing shadow modifier: Parent.WriteMe3
'object2, reference type Child and object type Child
'Testing Shadow: Child.WriteMe1
'Testing override: Child.WriteMe2
'Testing Shadow without explicitly writing shadow modifier: Child.WriteMe3
Вы можете скопировать его и попробовать сами. Поскольку вы видите, что затенение является поведением по умолчанию, а Visual Studio предупреждает вас, когда выполняется теневое копирование без явного написания модификатора тени.
Примечание. Для меня я никогда не использовал ссылку на базовый класс к дочернему объекту. Для таких случаев я всегда использую интерфейсы.
Я согласен с Джимом. Я никогда не нашел законного использования для Shadows. Обычно, если я это вижу, я предполагаю, что часть раздела кода должна быть реорганизована бит.
Я полагаю, что она существует, чтобы вы могли затенять метод из сборки, в которой у вас нет контроль над исходным кодом. В этом случае рефакторинг родительского класса будет невозможным.
Это недавняя ссылка MSDN: Различия между затенением и переопределением
Shadowing защищает от последующей модификации базового класса, которая вводит член, который вы уже определили в ваш производный класс. Обычно вы используете затенение в следующих случаях:
** Вы ожидаете, что ваш базовый класс может быть изменен, чтобы определить элемент с тем же именем, что и ваш. *
** Вы хотите свободу изменения типа элемента или последовательности вызовов. *
(я еще не исследовал использование в отношении области и типов)
Тенерирование, вероятно, не делает того, что вы думаете.
Рассмотрим следующие классы:
Public MustInherit Class A
Public Function fX() As Integer
Return 0
End Function
End Class
Public Class B
Inherits A
Public Shadows Function fX() As Integer
Return 1
End Function
End Class
Теперь я использую их:
Dim oA As A
Dim oB As New B
oA = oB
Вероятно, вы думаете, что oA и oB имеют одинаковое право?
Нет.
oA.fx = 0, в то время как oB.fx = 1
Imho это очень опасное поведение, и это почти не упоминается в документах.
Если вы использовали они будут одинаковыми.
Таким образом, хотя есть законные способы использования теней, вероятность того, что вы делаете, не является одним из них, и этого следует избегать.
Я думаю, что есть действительно два сценария, которые люди принимают здесь, и оба являются законными. Вы действительно можете разбить их на дизайнера базового класса и спустя годы разработчика, который реализует подкласс, который не может изменить базовый класс. Так что да, лучше всего переодеться, если у вас есть эта роскошь. Это чистый подход OOD.
С другой стороны, у вас может быть что-то вроде примера, приведенного выше, где вы находитесь на другом конце этого уравнения, чтобы реализовать подкласс, и вы не можете изменить тот факт, что метод, который вам нужно переопределить, не помечены как надменные. Возьмем, к примеру,
Public Shadows Function Focus() As Boolean
txtSearch.Focus()
Return MyBase.Focus()
End Function
. В этом случае я наследую свой класс из класса управления Winform, который, к сожалению, не отмечен как переопределяемый. На этом этапе я столкнулся с тем, что просто сделал код «чистым» или упростил его понимание. Клиент этого элемента управления просто хочет вызвать control.Focus () и, вероятно, все равно. Я мог бы назвать этот метод FocusSearchText () или Focus2 и т. Д., Но я считаю, что выше код намного проще для клиентского кода. Это правда, что если клиент затем переводит этот элемент управления в качестве базового класса и вызывает фокус, мой код не будет вызывать. Но это довольно отдаленно.
В конце концов, это сводится к решению суда, и вы должны будете сделать.
Shadow позволяет выполнять определенные действия, которые невозможно выполнить с переопределениями.
В моем собственном случае: у меня есть несколько классов таблиц с общей функциональностью; но для кого сами коллекции имеют разные типы.
Public Class GenericTable
Protected Friend Overridable Property Contents As System.Collections.Generic.List(Of GenericItem)
... do stuff ...
End Class
Тогда у меня есть конкретные isntances:
Public Class WidgetTable
Inherits GenericTable
Protected Friend Shadows Property Contents As System.Collections.Generic.List(Of Widget)
... stuff is inhereted ...
End Class
Я не мог переопределить, потому что тип был изменен.
Я нашел другое различие. См. Это:
Sub Main()
Dim X As New Derived
Dim Y As Base = New Derived
Console.WriteLine("X:" & X.Test())
Console.WriteLine("Y:" & Y.Test())
Console.WriteLine("X:" & CType(X, Base).Test)
Console.WriteLine("X:" & X.Func())
Console.WriteLine("Y:" & Y.Func())
Console.WriteLine("X:" & CType(X, Base).Func)
Console.ReadKey()
End Sub
Public Class Base
Public Overridable Function Func() As String
Return "Standard"
End Function
Function Test() As String
Return Me.Func()
End Function
End Class
Public Class Derived
Inherits Base
Public $$$ Function Func() As String
Return "Passed By Class1" & " - " & MyBase.Func
End Function
End Class
Если вы используете Overrides (где есть $$$), то нет возможности использовать класс Func on Base, если определение экземпляра Derived и если определение является базой, но экземпляр имеет тип Derived.
Если вы используете Shadows, единственный способ увидеть Func в производном классе - определить экземпляр как Derived и не перейти к метод базового класса (X.Test возвращает стандарт). Я думаю, что это главное: если я использую Shadows, метод не будет перегружать базовый метод внутри базовых методов.
Это подход OOP Overloads. Если я получаю класс и НЕ НУЖНО, я хочу, чтобы метод вызывался, я должен использовать Overloads. Для экземпляров моих объектов нет способа вернуть «Стандарт» (за исключением использования отражений, я думаю). Я думаю, что intellisense немного путается. Если я выделил Y.Func, будет выделен Func в базовый класс, но будет выполнен Func в производный класс.
С помощью Shadows новый метод доступен только напрямую. Как и Overloads, но скрывая перегрузки базового класса (я думаю, что это ошибка, возвращаемая перед компиляцией, потому что вы можете вызвать ее с помощью трансляции, например, неявной, сделанной с использованием перегрузки).
Переопределения - более нормальный квалификатор. Если дочерний класс переопределяет функцию базового класса таким образом, то независимо от того, как ссылается дочерний объект (с использованием базового класса или ссылки на дочерний класс), вызывается дочерняя функция.
С другой стороны, если функция дочернего класса Shadows выполняет функцию базового класса, тогда дочерний объект, к которому обращаются через ссылку базового класса, будет использовать эту функцию базового класса, несмотря на то, что это дочерний объект. Определение дочерней функции используется только при обращении к дочернему объекту с использованием соответствующей дочерней ссылки.
Пример затенения: предположим, что вы хотите использовать функцию в стороннем компоненте, но функция защищена. Вы можете обойти это ограничение простым наследованием и выставить затененную функцию, которая в основном вызывает его базовую функцию:
Public Class Base
Protected Sub Configure()
....
End Sub
End Class
Public Class Inherited
Inherits Base
Public Shadows Sub Configure()
MyBase.Configure()
End Sub
End Class
Использование теней редко, но верно. Кроме того, вы не можете переопределить общий (статический) метод. Поэтому вы должны затенять общий метод, если хотите «переопределить» его.
Тени могут быть очень полезными, если вы пишете обертку вокруг существующего элемента управления.
Например, рядом со списком. Затеняя AutoCompleteSource
, вы можете помешать ему установить незаконное значение для вашего специального вида combobox, даже когда оно будет передано в обычное поле со списком. Или выполните предварительную обработку, прежде чем использовать mybase.AutoCompleteSource = value
в свойстве shadowing.
Я хотел использовать System.Web.HttpContext.Current.Response
вместо Response.redirect
и нуждался в удобстве для кода как Response.redirect
. Я определил свойство readonly с именем Response
, чтобы затенять оригинал в базовом классе. Я не мог использовать переопределения, поскольку это свойство не является переопределяемым. Очень удобно:)
Ключевое слово «тени» по существу говорит: «Если кто-либо, кто обращается к этому объекту, знает, что он имеет этот тип или один из его потомков, используйте этот элемент, иначе используйте базовый». Простейшим примером этого может быть базовый класс ThingFactory, который включает в себя метод «MakeNew», который возвращает Thing, и класс CarFactory, полученный от ThingFactory, метод «MakeNew» всегда возвращает Вещь, которая будет иметь производный тип Car. Если рутина знает, что ThingFactory, с которым он держится, происходит, в частности, CarFactory, тогда он будет использовать затененный CarFactory.MakeNew (если таковой существует), который может указывать тип возврата в качестве автомобиля. Если рутина не знает, что его ThingFactory на самом деле является CarFactory, он будет использовать не скрытый MakeNew (который должен вызывать внутренний защищенный переопределяемый метод MakeDerivedThing).
Кстати, другое хорошее использование теней для предотвращения доступа к производным классам защищенных методов, которые больше не будут работать. Невозможно просто скрыть член от производных классов, отличных от назначения нового, но можно запретить производным классам что-либо делать с защищенным членом, объявив новый защищенный пустой класс с этим именем. Например, если вызов объекта MemberwiseClone на объекте сломает его, можно объявить:
Protected Shadows Class MemberwiseClone End ClassОбратите внимание, что это не нарушает принципы ООП, такие как Принцип замещения Лискова, поскольку это применимо только в случаях, когда производный класс может использоваться вместо объект базового класса. Если Foo и Bar наследуются от Boz, метод, который принимает параметр Boz, может быть законно передан в Foo или Bar вместо этого. С другой стороны, объект типа Foo будет знать, что его объект базового класса имеет тип Boz. Это никогда не будет чем-то другим (например, он не будет баром).
Иногда небольшой пример действительно помогает понять разницу техническим способом.
Sub Main()
Dim o As New ChildClass
Console.WriteLine(o.GetValOverride()) ' Prints 2
Console.WriteLine(o.GetValShadow()) ' Prints 2
Console.WriteLine(CType(o, ParentClass).GetValOverride()) ' Prints 2
Console.WriteLine(CType(o, ParentClass).GetValShadow()) ' Prints 1
Console.ReadLine()
End Sub
Class ParentClass
Public Overridable Function GetValOverride() As String
Return "1"
End Function
Public Function GetValShadow() As String
Return "1"
End Function
End Class
Class ChildClass
Inherits ParentClass
Public Overrides Function GetValOverride() As String
Return "2"
End Function
Public Shadows Function GetValShadow() As String
Return "2"
End Function
End Class
Переопределения - расширение или создание альтернативных функций для метода.
Пример: добавление или расширение функциональности события Paint в окне.
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e) ' retain the base class functionality
'add code for extended functionality here
End Sub
Тени - переопределяет унаследованный метод и заставляет его использовать для всех классов, созданных с этим типом. Другими словами, метод не перегружен, но переопределен и методы базового класса недоступны, что заставляет использовать функцию, объявленную в классе. Тени сохраняют или сохраняют определение метода таким образом, что оно не уничтожается, если методы базового класса модифицированы.
Пример: принудительно использовать все классы «B» для использования его oddball. Добавьте определение, которое, если A class Add методы изменены, это не повлияет на добавление B. (Скрывает все методы «Добавить» базового класса. Не сможет вызвать A.Add (x, y, z) из экземпляра B.)
Public Class A
Public Function Add(ByVal x As Integer, ByVal y As Integer) As Integer
Return x + y
End Function
Public Function Add(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer) As Integer
Return x + y + z
End Function
End Class
Public Class B
Inherits A
Public Shadows Function Add(ByVal x As Integer, ByVal y As Integer) As Integer
Return x - y
End Function
End Class